@bdsoft/element 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bdsoft/element",
3
3
  "private": false,
4
- "version": "1.1.0",
4
+ "version": "1.1.2",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "scripts": {
@@ -10,8 +10,8 @@
10
10
  "preview": "vite preview"
11
11
  },
12
12
  "dependencies": {
13
- "@element-plus/icons-vue": "^2.3.1",
14
- "element-plus": "^2.11.5",
13
+ "@element-plus/icons-vue": "^2.3.2",
14
+ "element-plus": "2.13.1",
15
15
  "splitpanes": "4.0.4"
16
16
  }
17
17
  }
@@ -27,106 +27,123 @@
27
27
  }
28
28
 
29
29
  // tab样式重写--圆滑风格
30
- .bdtabs .el-tabs__header {
31
- margin: 0px !important;
32
- height: 34px !important;
33
- .el-tabs__nav-wrap {
34
- margin-bottom: -3px;
35
- }
36
- .el-tabs__nav {
37
- border: 0px !important;
38
- }
39
- .el-tabs__item {
40
- padding: 0 10px;
41
- height: 30px !important;
42
- border-style: solid;
43
- border-color: transparent !important;
44
- }
45
- .is-active {
46
- background: #e5eeff !important;
47
- z-index: 1;
30
+ .bdtabs.el-tabs {
31
+ & > .el-tabs__header {
32
+ margin: 0px !important;
33
+ height: 34px !important;
34
+ .el-tabs__nav-wrap {
35
+ margin-bottom: -3px;
36
+ }
37
+ .el-tabs__nav {
38
+ border: 0px !important;
39
+ }
40
+ .el-tabs__item {
41
+ padding: 0 10px;
42
+ height: 30px !important;
43
+ border-style: solid;
44
+ border-color: transparent !important;
45
+ }
46
+ .is-active {
47
+ background: #e5eeff !important;
48
+ z-index: 1;
48
49
 
49
- -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzAiIGhlaWdodD0iNzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0ibm9uZSI+PHBhdGggZD0iTTEwMC4yMzYgOTkuODgzQzQ1LjAwOCAxMDAuMDEyLjEzMiA1NS4zNDQuMDAzLjExN2wuMjMzIDEwMCAxMDAtLjIzNHoiIG9wYWNpdHk9InVuZGVmaW5lZCIgc3Ryb2tlPSJudWxsIiBmaWxsPSIjRjhFQUU3Ii8+PHBhdGggZD0iTS0uNjM4IDcuMzEyYy4xMiAwIC4yMTguMDU4LjQ3Ny4xMi4yMzIuMDU0LjI3My4wMzQuMzU4LjExOS4wODQuMDg0LjM1NyAwIC40NzYgMGguMzU4TTI4LjkyMSA2OS4wNTJ2LjU5Nk0yOC45MjEgNjguNDU3aC4xMTl2MS43ODhoLS4xMTl6TTM2LjY2OSA1MS4yOTNoMTkuMDd2NC44ODdoLTE5LjA3eiIgc3Ryb2tlPSJudWxsIi8+PC9zdmc+),
50
- url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzAiIGhlaWdodD0iNzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0ibm9uZSI+PHBhdGggc3Ryb2tlPSJudWxsIiBmaWxsPSIjRjhFQUU3IiBkPSJNNjkuOTU0LjE0Yy0uMjI5IDU1LjIyOC00NS4xODYgOTkuODE0LTEwMC40MTMgOTkuNTg1bDk5Ljk5OS40MTRMNjkuOTU0LjE0eiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBkPSJNLS42MzggNy4zMTJjLjEyIDAgLjIxOC4wNTguNDc3LjEyLjIzMi4wNTQuMjczLjAzNC4zNTguMTE5LjA4NC4wODQuMzU3IDAgLjQ3NiAwaC4zNThNMjguOTIxIDY5LjA1MnYuNTk2TTI4LjkyMSA2OC40NTdoLjExOXYxLjc4OGgtLjExOXpNMzYuNjY5IDUxLjI5M2gxOS4wN3Y0Ljg4N2gtMTkuMDd6IiBzdHJva2U9Im51bGwiLz48L3N2Zz4=),
51
- url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHJ4PSI4IiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjRjhFQUU3Ii8+PC9zdmc+);
52
- -webkit-mask-size:
53
- 18px 30px,
54
- 20px 30px,
55
- calc(100% - 30px) calc(100% + 17px);
56
- -webkit-mask-position:
57
- right bottom,
58
- left bottom,
59
- center top;
60
- -webkit-mask-repeat: no-repeat;
61
- .el-dropdown span {
62
- color: #0256ff !important;
63
- margin-left: 10px;
50
+ -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzAiIGhlaWdodD0iNzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0ibm9uZSI+PHBhdGggZD0iTTEwMC4yMzYgOTkuODgzQzQ1LjAwOCAxMDAuMDEyLjEzMiA1NS4zNDQuMDAzLjExN2wuMjMzIDEwMCAxMDAtLjIzNHoiIG9wYWNpdHk9InVuZGVmaW5lZCIgc3Ryb2tlPSJudWxsIiBmaWxsPSIjRjhFQUU3Ii8+PHBhdGggZD0iTS0uNjM4IDcuMzEyYy4xMiAwIC4yMTguMDU4LjQ3Ny4xMi4yMzIuMDU0LjI3My4wMzQuMzU4LjExOS4wODQuMDg0LjM1NyAwIC40NzYgMGguMzU4TTI4LjkyMSA2OS4wNTJ2LjU5Nk0yOC45MjEgNjguNDU3aC4xMTl2MS43ODhoLS4xMTl6TTM2LjY2OSA1MS4yOTNoMTkuMDd2NC44ODdoLTE5LjA3eiIgc3Ryb2tlPSJudWxsIi8+PC9zdmc+),
51
+ url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzAiIGhlaWdodD0iNzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgZmlsbD0ibm9uZSI+PHBhdGggc3Ryb2tlPSJudWxsIiBmaWxsPSIjRjhFQUU3IiBkPSJNNjkuOTU0LjE0Yy0uMjI5IDU1LjIyOC00NS4xODYgOTkuODE0LTEwMC40MTMgOTkuNTg1bDk5Ljk5OS40MTRMNjkuOTU0LjE0eiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBkPSJNLS42MzggNy4zMTJjLjEyIDAgLjIxOC4wNTguNDc3LjEyLjIzMi4wNTQuMjczLjAzNC4zNTguMTE5LjA4NC4wODQuMzU3IDAgLjQ3NiAwaC4zNThNMjguOTIxIDY5LjA1MnYuNTk2TTI4LjkyMSA2OC40NTdoLjExOXYxLjc4OGgtLjExOXpNMzYuNjY5IDUxLjI5M2gxOS4wN3Y0Ljg4N2gtMTkuMDd6IiBzdHJva2U9Im51bGwiLz48L3N2Zz4=),
52
+ url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHJ4PSI4IiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjRjhFQUU3Ii8+PC9zdmc+);
53
+ -webkit-mask-size: 18px 30px, 20px 30px, calc(100% - 30px) calc(100% + 17px);
54
+ -webkit-mask-position: right bottom, left bottom, center top;
55
+ -webkit-mask-repeat: no-repeat;
56
+ .el-dropdown span {
57
+ color: #0256ff !important;
58
+ margin-left: 10px;
59
+ }
64
60
  }
65
61
  }
66
62
  }
67
63
  // tab样式重写--卡片风格
68
- .bdtabs2 .el-tabs__header {
69
- margin: 0px !important;
70
- height: 34px !important;
71
- .el-tabs__nav-wrap {
72
- margin-bottom: -3px;
73
- }
74
- .el-tabs__nav {
75
- border: 0px !important;
76
- }
77
- .el-tabs__item {
78
- padding: 0 10px;
79
- height: 28px !important;
80
- border: 1px solid #d9d9d9;
81
- margin-left: 4px;
82
- margin-top:2px;
83
- margin-bottom:2px;
84
- // border-color: transparent !important;
85
- }
86
- .is-active {
87
- background: #e5eeff !important;
88
- z-index: 1;
64
+ .bdtabs2.el-tabs {
65
+ & > .el-tabs__header {
66
+ margin: 0px !important;
67
+ height: 34px !important;
68
+ .el-tabs__nav-wrap {
69
+ margin-bottom: -3px;
70
+ }
71
+ .el-tabs__nav {
72
+ border: 0px !important;
73
+ }
74
+ .el-tabs__item {
75
+ padding: 0 10px;
76
+ height: 28px !important;
77
+ border: 1px solid #d9d9d9;
78
+ margin-left: 4px;
79
+ margin-top: 2px;
80
+ margin-bottom: 2px;
81
+ // border-color: transparent !important;
82
+ }
83
+ .is-active {
84
+ background: #e5eeff !important;
85
+ z-index: 1;
89
86
 
90
-
91
- .el-dropdown span {
92
- color: #0256ff !important;
93
- margin-left: 10px;
87
+ .el-dropdown span {
88
+ color: #0256ff !important;
89
+ margin-left: 10px;
90
+ }
94
91
  }
95
92
  }
96
93
  }
97
94
 
98
95
  // tab样式重写--灵动风格
99
- .bdtabs3 .el-tabs__header {
100
- margin: 0px !important;
101
- height: 34px !important;
102
- .el-tabs__nav-wrap {
103
- margin-bottom: -3px;
104
- }
105
- .el-tabs__nav {
106
- border: 0px !important;
107
- }
108
- .el-tabs__item {
109
- padding: 0 10px;
110
- height: 28px !important;
111
- border: 0px solid #d9d9d9;
112
- // margin-left: 4px;
113
- // margin-top:2px;
114
- // margin-bottom:2px;
115
- // border-color: transparent !important;
116
- }
117
- .is-active {
118
- background: #e5eeff !important;
119
- z-index: 1;
96
+ .bdtabs3.el-tabs {
97
+ & > .el-tabs__header {
98
+ margin: 0px !important;
99
+ height: 34px !important;
100
+ .el-tabs__nav-wrap {
101
+ margin-bottom: -3px;
102
+ }
103
+ .el-tabs__nav {
104
+ border: 0px !important;
105
+ }
106
+ .el-tabs__item {
107
+ padding: 0 10px;
108
+ height: 28px !important;
109
+ border: 0px solid #d9d9d9;
110
+ // margin-left: 4px;
111
+ // margin-top:2px;
112
+ // margin-bottom:2px;
113
+ // border-color: transparent !important;
114
+ }
115
+ .is-active {
116
+ background: #e5eeff !important;
117
+ z-index: 1;
120
118
 
121
-
122
- .el-dropdown span {
123
- color: #0256ff !important;
124
- margin-left: 10px;
119
+ .el-dropdown span {
120
+ color: #0256ff !important;
121
+ margin-left: 10px;
122
+ }
125
123
  }
126
124
  }
127
125
  }
126
+ // tab样式重写--顶部线条风格
127
+ .bdtabs4.el-tabs {
128
+ & > .el-tabs__header {
129
+ border-bottom: 1px solid #e4e7ed !important;
130
+ .el-tabs__nav {
131
+ border-right: 1px solid #fff;
132
+ border-left: 1px solid #fff;
133
+ }
128
134
 
129
-
135
+ .el-tabs__item {
136
+ border-top: 1px solid #fff;
137
+ border-left: 1px solid #fff;
138
+ border-right: 1px solid #fff;
139
+ }
140
+ .is-active {
141
+ border-top: 2px solid #409eff !important;
142
+ border-left: 1px solid #e4e7ed !important;
143
+ border-right: 1px solid #e4e7ed !important;
144
+ }
145
+ }
146
+ }
130
147
  // 分割线样式
131
148
  .bddivider > .el-drawer__body > .el-divider--horizontal {
132
149
  border-top: 1px solid #e5eeff !important;
@@ -95,9 +95,9 @@ var CountUp = function (target, startVal, endVal, decimals, duration, options) {
95
95
  self.printValue = function (value) {
96
96
  var result = self.formattingFn(value)
97
97
 
98
- if (self.d.tagName === 'INPUT') {
98
+ if (self.d?.tagName === 'INPUT') {
99
99
  this.d.value = result
100
- } else if (self.d.tagName === 'text' || self.d.tagName === 'tspan') {
100
+ } else if (self.d?.tagName === 'text' || self.d?.tagName === 'tspan') {
101
101
  this.d.textContent = result
102
102
  } else {
103
103
  this.d.innerHTML = result
@@ -8,12 +8,16 @@
8
8
  <script setup>
9
9
  import { ref, reactive, nextTick, watch, onMounted } from "vue";
10
10
  import { CountUp } from './countUp.js'
11
-
12
11
  const props = defineProps({
13
12
  idName: {
14
13
  type: String,
15
14
  default: ''
16
15
  },
16
+ // 标题显示
17
+ title: {
18
+ type: String,
19
+ default: ''
20
+ },
17
21
  startVal: {
18
22
  type: Number,
19
23
  default: 0
@@ -28,7 +32,7 @@ const props = defineProps({
28
32
  },
29
33
  color: {
30
34
  type: String,
31
- default: '#fff' // D9524E
35
+ default: '#3b3a3a' // D9524E
32
36
  },
33
37
  introText: {
34
38
  type: String,
@@ -51,9 +55,7 @@ const props = defineProps({
51
55
  default: 500
52
56
  }
53
57
  })
54
- const className= ref('')
55
- // const countUpRef = ref(null)
56
- // const countUp = new CountUp(countUpRef.value, props.endVal
58
+ const className = ref('')
57
59
 
58
60
  function transformValue (val) {
59
61
  let endVal = 0
@@ -88,7 +90,7 @@ onMounted(() => {
88
90
 
89
91
  const res = transformValue(props.endVal)
90
92
  const endVal = props.endVal // res.val
91
-
93
+ let idname = props.idName
92
94
  demo = new CountUp(props.idName, props.startVal, endVal, props.decimals, props.duration, props.options)
93
95
  if (!demo.error) {
94
96
  demo.start()
@@ -100,13 +102,13 @@ onMounted(() => {
100
102
  </script>
101
103
  <template>
102
104
  <div>
103
- <div :class="className" :style="{ textAlign: 'center', color: color, fontSize: countSize, fontWeight: countWeight,fontFamily:'PingFang SC' }">
105
+ <div v-if="title" style="color: #606266;">{{ title }}</div>
106
+ <div :class="className"
107
+ :style="{ textAlign: 'center', color: color, fontSize: countSize, fontWeight: countWeight, fontFamily: 'PingFang SC' }">
104
108
  <span v-cloak :id="idName">{{ startVal }}</span>
105
109
  </div>
106
110
  <slot name="intro"></slot>
107
111
  </div>
108
112
  </template>
109
113
 
110
- <style lang="scss" scoped>
111
-
112
- </style>
114
+ <style lang="scss" scoped></style>
@@ -6,7 +6,7 @@
6
6
  * @LastEditTime: 最后更新时间
7
7
  -->
8
8
  <script setup>
9
- import { ref, computed, watch, onMounted, defineEmits, nextTick } from 'vue'
9
+ import { ref, computed, watch, onMounted, nextTick } from 'vue'
10
10
  const emits = defineEmits(['liClick'])
11
11
  const props = defineProps({
12
12
  imgNum: {
@@ -6,7 +6,7 @@
6
6
  * @LastEditTime: 最后更新时间
7
7
  -->
8
8
  <script setup>
9
- import { ref, computed, watch, onMounted, defineEmits } from 'vue'
9
+ import { ref, computed, watch, onMounted } from 'vue'
10
10
  import { parseTime } from '../../utils/index.js'
11
11
  const emits = defineEmits(['liClick', 'liRightClick', 'pageChange', 'titleSearch', 'addNew'])
12
12
  const props = defineProps({
@@ -41,7 +41,7 @@
41
41
  </div>
42
42
  </template>
43
43
  <script setup>
44
- import { defineComponent, ref, reactive, computed, watch, onMounted, inject, nextTick, onBeforeMount, onUnmounted, defineEmits } from 'vue'
44
+ import { defineComponent, ref, reactive, computed, watch, onMounted, inject, nextTick, onBeforeMount, onUnmounted } from 'vue'
45
45
  const emits = defineEmits([])
46
46
  const props = defineProps({
47
47
  bdsdk: {
@@ -13,7 +13,7 @@
13
13
 
14
14
  <script setup>
15
15
  import { scrollTo } from './scroll-to.js';
16
- import {computed, defineEmits } from 'vue';
16
+ import {computed } from 'vue';
17
17
 
18
18
  const emits = defineEmits(['update:page', 'update:pageSize', 'pagination']);
19
19
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bdsoft/element-screenfull",
3
- "version": "1.0.0",
3
+ "version": "1.1.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -13,6 +13,10 @@ import BdLayout4 from './components/layout/layout4.vue'
13
13
  import HeadSearch from './xm_components/HeadSearch/index.vue'
14
14
  // 里程碑组件
15
15
  import Milestone from './xm_components/Milestone/index.vue'
16
+ // 多维数据统计组件
17
+ import StatisticalCard from './xm_components/StatisticalCard/index.vue'
18
+ // 多数据指标统计
19
+ import MultiStatisticalCard from './xm_components/MultiStatisticalCard/index.vue'
16
20
  import BDCarousel from './components/carousel/index.vue'
17
21
  import BdFormItem from './components/form/FormItem.vue'
18
22
  import BdForm from './components/form/Form.vue'
@@ -65,6 +69,8 @@ export {
65
69
  BdLayout4,
66
70
  HeadSearch,
67
71
  Milestone,
72
+ StatisticalCard,
73
+ MultiStatisticalCard,
68
74
  BdEmpty,
69
75
  BdInvalid,
70
76
  BDCarousel,
@@ -1,6 +1,6 @@
1
1
 
2
- ## 使用说明
3
-
2
+ ## 搜索框使用说明
3
+ 功能: 首页搜索框 带搜索历史记录功能
4
4
  >>> 注意:
5
5
  ```
6
6
  import {HeadSearch} from '@bdsoft/element'
@@ -0,0 +1,114 @@
1
+ <!--
2
+ * @FileDescription: 核心指标统计组件
3
+ * @Author: 李兵泉
4
+ * @Date: 2025-11-26
5
+ * @LastEditors: 最后更新作者
6
+ * @LastEditTime: 最后更新时间
7
+ -->
8
+ <template>
9
+ <el-row :gutter="0" class="basicwarp" :style="{ height: height }">
10
+ <!-- 动态渲染指标项 valueColor-->
11
+ <el-col
12
+ v-for="(item, index) in indicators"
13
+ :key="index"
14
+ @click="handleIndicatorClick(item, index)"
15
+ :md="item.colSize || 4"
16
+ class="text-center mb-4"
17
+ style="cursor: pointer"
18
+ >
19
+ <BdCountUp
20
+ class="infor-intro-num user-created-count"
21
+ :title="item.title"
22
+ :id-name="item.key"
23
+
24
+ :endVal="item.value"
25
+ countSize="30px"
26
+ :color="item.valueColor || ''"
27
+ :countWeight="700"
28
+ @click="handleItemClick(item, index)"
29
+ >
30
+ </BdCountUp>
31
+ </el-col>
32
+ </el-row>
33
+ </template>
34
+ <script setup>
35
+ import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
36
+ // import { useTransition } from '@vueuse/core'
37
+ import BdCountUp from '../../components/countup/index.vue'
38
+
39
+ // 定义自定义事件,用于向父组件传递点击信息
40
+ const emit = defineEmits(['indicator-click'])
41
+ // 存储每个指标的过渡值
42
+ const indicatorValues = ref({})
43
+ // 组件props定义
44
+ const props = defineProps({
45
+ height: {
46
+ type: String,
47
+ default: '200px'
48
+ },
49
+ // 指标数据列表
50
+ indicators: {
51
+ type: Array,
52
+ default: () => []
53
+ }
54
+ })
55
+
56
+ const handleItemClick = (item, index) => {
57
+ // 触发自定义事件,传递点击的指标项数据和索引
58
+ if (item.onClick) {
59
+ item.onClick(item, index)
60
+ }
61
+ }
62
+ // 处理指标项点击事件
63
+ const handleIndicatorClick = (item, index) => {
64
+ // 触发自定义事件,传递点击的指标项数据和索引
65
+ emit('indicator-click', {
66
+ item, // 点击的指标项完整数据
67
+ index // 点击的指标项索引
68
+ })
69
+ }
70
+
71
+ watch(
72
+ () => props.indicators,
73
+ (newIndicators) => {
74
+ if (newIndicators && newIndicators.length > 0) {
75
+ // nextTick(() => {
76
+ // props.indicators.forEach(item => {
77
+ // indicatorValues.value[item.key] = useNumberTransition(ref(0), {
78
+ // duration: item.duration || 1000,
79
+ // })
80
+ // })
81
+ // });
82
+ }
83
+ },
84
+ {
85
+ immediate: true
86
+ }
87
+ )
88
+
89
+ // 初始化过渡动画
90
+ onMounted(() => {})
91
+ </script>
92
+
93
+ <style lang="scss" scoped>
94
+ .basicwarp {
95
+ display: flex;
96
+ align-items: center;
97
+ height: 100%;
98
+ width: 100%;
99
+ }
100
+
101
+ :deep(.el-statistic__head) {
102
+ font-size: 17px;
103
+ text-align: center;
104
+ color: #737070 !important;
105
+ }
106
+
107
+ :deep(.el-statistic__content) {
108
+ font-size: 28px;
109
+ text-align: center;
110
+ font-weight: 600;
111
+ color: #737070 !important;
112
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
113
+ }
114
+ </style>
@@ -0,0 +1,29 @@
1
+ ## 多指标显示组件
2
+
3
+ <template>
4
+ <MultiStatisticalCard :indicators="indicators" ></MultiStatisticalCard>
5
+ </template>
6
+ <script setup>
7
+ import { ref, reactive, computed, watch, onMounted } from "vue";
8
+ import { MultiStatisticalCard } from '@bdsoft/element'
9
+
10
+ const indicators = [
11
+ { key: 'oil_prod_cum', title: '累计油量(t)', valueColor:'red',value: 5656 },
12
+ { key: 'bncl', title: '本年产量(t)', valueColor:'red',value: 16 },
13
+ { key: 'sncl', title: '上年产量(t)',valueColor:'red', value: 116 },
14
+ // { key: 'sncl2', title: '上年产量(t)', valueColor:'red',value: 116 },
15
+ { key: 'zrcl', title: '昨日产量(t)',valueColor:'red', value: 2346 }
16
+ ]
17
+ </script>
18
+
19
+ ### 触发点击事件
20
+
21
+ <MultiStatisticalCard :indicators="indicators" @indicator-click="handleClick"></MultiStatisticalCard>
22
+
23
+ <script setup>
24
+ const handleClick = (data) => {
25
+ console.log('点击了指标项:', data.item);
26
+ console.log('指标项索引:', data.index);
27
+ // 处理点击逻辑
28
+ };
29
+ </script>
@@ -0,0 +1,196 @@
1
+ <!--
2
+ * @FileDescription: 统计组件
3
+ * @Author: 李兵泉
4
+ * @Date: 2025-11-26
5
+ * @LastEditors: 最后更新作者
6
+ * @LastEditTime: 最后更新时间
7
+ -->
8
+ <template>
9
+ <!-- 投资总额卡片容器 -->
10
+ <div
11
+ class="investment-card"
12
+ :style="{ width: width }"
13
+ v-if="_datas && _datas != ''"
14
+ >
15
+ <!-- 循环渲染数据项(空数据则不显示) -->
16
+ <div class="data-item">
17
+ <!-- 标题行(带提示图标) -->
18
+ <div class="title-row">
19
+ <span class="title">{{ _datas[0]?.title }}</span>
20
+ <el-tooltip v-if="tip" :content="tip" placement="top">
21
+ <el-icon size="16px" class="info-icon"><question-filled /></el-icon>
22
+ </el-tooltip>
23
+ </div>
24
+ <!-- 数值行 -->
25
+ <div
26
+ class="value"
27
+ :style="{
28
+ color: _datas[0]?.valueColor || '#000',
29
+ cursor: _datas[0]?.onClick ? 'pointer' : 'default',
30
+ }"
31
+ @click="handleItemClick(_datas[0], 0)"
32
+ >
33
+ {{ _datas[0]?.value }}
34
+ </div>
35
+ </div>
36
+ <div style="display: flex" @click="handleItemClick(_datas[1], 1)">
37
+ <!-- 数组 up2 -->
38
+ <div v-if="_datas[1]" class="extra-row">
39
+ <span class="extra-item">
40
+ {{ _datas[1]?.title }}
41
+ <span :class="['trend', _datas[1]?.trend === 'up' ? 'up' : 'down']">
42
+ {{ _datas[1]?.value }}
43
+ <el-icon class="trend-icon">
44
+ <component
45
+ :is="_datas[1]?.trend === 'up' ? 'caret-top' : 'caret-bottom'"
46
+ />
47
+ </el-icon>
48
+ </span>
49
+ </span>
50
+ </div>
51
+ <!-- 数组 down3 -->
52
+ <div
53
+ v-if="_datas[2]"
54
+ class="extra-row"
55
+ style="margin-left: 10%"
56
+ @click="handleItemClick(_datas[2], 2)"
57
+ >
58
+ <span class="extra-item">
59
+ {{ _datas[2]?.title }}
60
+ <span :class="['trend', _datas[2]?.trend === 'up' ? 'up' : 'down']">
61
+ {{ _datas[2]?.value }}
62
+ <el-icon class="trend-icon">
63
+ <component
64
+ :is="_datas[2]?.trend === 'up' ? 'caret-top' : 'caret-bottom'"
65
+ />
66
+ </el-icon>
67
+ </span>
68
+ </span>
69
+ </div>
70
+ </div>
71
+ <el-divider style="margin: 10px 0" />
72
+ <div
73
+ v-if="_datas[3]"
74
+ class="extra-row"
75
+ @click="handleItemClick(_datas[3], 3)"
76
+ >
77
+ <span class="extra-item" style="color: #595858">
78
+ {{ _datas[3]?.title }}
79
+ <span class="trend">
80
+ {{ _datas[3]?.value }}
81
+ </span>
82
+ </span>
83
+ </div>
84
+ </div>
85
+ </template>
86
+
87
+ <script setup>
88
+ import { ref, watch } from "vue";
89
+
90
+ const _datas = ref([]);
91
+ // 接收父组件传入的4组数据(数组,每个对象对应一组数据)
92
+ const props = defineProps({
93
+ // 组件默认宽度
94
+ width: {
95
+ type: String,
96
+ default: "350px",
97
+ },
98
+ // 右上角提示信息
99
+ tip: {
100
+ type: String,
101
+ default: "",
102
+ },
103
+ // 数据列表 格式参考readme
104
+ dataList: {
105
+ type: Array,
106
+ default: () => [],
107
+ },
108
+ });
109
+ const handleItemClick = (item, index) => {
110
+ // 触发自定义事件,传递点击的指标项数据和索引
111
+ if (item && item.onClick) {
112
+ item.onClick(item, index);
113
+ }
114
+ };
115
+ watch(
116
+ () => props.dataList,
117
+ (newVal) => {
118
+ if (newVal && newVal.length > 0) {
119
+ _datas.value = newVal;
120
+ }
121
+ },
122
+ {
123
+ immediate: true,
124
+ }
125
+ );
126
+ </script>
127
+
128
+ <style scoped>
129
+ .investment-card {
130
+ background: #fff;
131
+ border-radius: 8px;
132
+ padding: 12px;
133
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
134
+ }
135
+
136
+ .data-item {
137
+ margin-bottom: 12px;
138
+ }
139
+
140
+ .title-row {
141
+ display: flex;
142
+ justify-content: space-between;
143
+ align-items: center;
144
+ margin-bottom: 8px;
145
+ color: #666;
146
+ font-size: 14px;
147
+ }
148
+
149
+ .info-icon {
150
+ cursor: pointer;
151
+ color: #999;
152
+ }
153
+
154
+ .value {
155
+ font-size: 28px;
156
+ font-weight: bold;
157
+ margin-bottom: 8px;
158
+ }
159
+
160
+ .extra-row {
161
+ display: flex;
162
+ gap: 16px;
163
+ margin-bottom: 8px;
164
+ font-size: 14px;
165
+ }
166
+
167
+ .extra-item {
168
+ display: flex;
169
+ align-items: center;
170
+ color: #999;
171
+ }
172
+
173
+ .trend {
174
+ margin-left: 4px;
175
+ }
176
+
177
+ .trend.up {
178
+ color: #f56c6c;
179
+ /* 红色-上升 */
180
+ }
181
+
182
+ .trend.down {
183
+ color: #67c23a;
184
+ /* 绿色-下降 */
185
+ }
186
+
187
+ .trend-icon {
188
+ font-size: 12px;
189
+ margin-left: 2px;
190
+ }
191
+
192
+ .additional {
193
+ font-size: 14px;
194
+ color: #666;
195
+ }
196
+ </style>
@@ -0,0 +1,41 @@
1
+ ## 统计数组组件
2
+
3
+ ```
4
+
5
+ <template>
6
+ <StatisticalCard :dataList="dataList" tip="投资总额说明111"></StatisticalCard>
7
+ </template>
8
+ <script setup>
9
+ import { ref, reactive, computed, watch, onMounted } from "vue";
10
+ import { StatisticalCard } from '@bdsoft/element'
11
+
12
+ const dataList = ref([
13
+ {
14
+ title: '总用户数',
15
+ value: 1024,
16
+ valueColor:'red',
17
+ trend: '',
18
+ },
19
+ {
20
+ title: '活跃用户数',
21
+ value: 768,
22
+ valueColor:'',
23
+ trend: 'up',
24
+ },
25
+ {
26
+ title: '新增用户数',
27
+ value: 256,
28
+ valueColor:'',
29
+ trend: 'down',
30
+ },
31
+ {
32
+ title: '付费用户数',
33
+ value: 128,
34
+ valueColor:'',
35
+ trend: ''
36
+ }
37
+ ]);
38
+ </script>
39
+
40
+ <style lang="scss" scoped></style>
41
+ ```
package/utils/message.js CHANGED
@@ -61,28 +61,23 @@ export function showconfirm(done, confirmtitle = '确认关闭?', showtext = { t
61
61
 
62
62
  /**
63
63
  * 信息提示框
64
- * @param {*} msg
65
- * @param {*} type
66
- * @param {*} title
67
- * @param {*} position
68
- * @param {*} dangerouslyUseHTMLString
64
+ * @param {*} msg
65
+ * @param {*} type
66
+ * @param {*} title
67
+ * @param {*} position
68
+ * @param {*} dangerouslyUseHTMLString
69
69
  */
70
- export function shownotiinfo(msg, type = 'info',title='提示',position='bottom-right',dangerouslyUseHTMLString=false) {
70
+ export function shownotiinfo(msg, type = 'info', title = '提示', position = 'bottom-right', dangerouslyUseHTMLString = false) {
71
71
  ElNotification({
72
72
  title: title,
73
73
  position: position,
74
74
  message: msg,
75
- dangerouslyUseHTMLString:dangerouslyUseHTMLString,
75
+ dangerouslyUseHTMLString: dangerouslyUseHTMLString,
76
76
  type: type
77
77
  })
78
78
  }
79
79
 
80
- export function showconfirminfo(
81
- msg = '确认删除?',
82
- showtext = { type: '', position: 'bottom-right', title: '提示', dangerouslyUseHTMLString: true },
83
- fn1,
84
- fn2
85
- ) {
80
+ export function showconfirminfo(msg = '确认删除?', showtext = { type: '', position: 'bottom-right', title: '提示', dangerouslyUseHTMLString: true }, fn1, fn2) {
86
81
  // 按钮
87
82
  const btn1 = h(ElButton, {
88
83
  innerText: '立即刷新',
@@ -138,7 +133,6 @@ export function confirm(confirmtitle = '确认关闭?') {
138
133
  return ElMessageBox.confirm(confirmtitle)
139
134
  }
140
135
 
141
-
142
136
  export function showloading(msg, duration = 0, showClose = true) {
143
137
  ElMessage({
144
138
  // <svg viewBox="0 0 1024 1024" focusable="false" data-icon="loading" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path></svg>
@@ -151,12 +145,16 @@ export function showloading(msg, duration = 0, showClose = true) {
151
145
 
152
146
  // loading加载 closeLoading
153
147
  let loadingObj = null
154
- export function showLoading(msg) {
148
+ export function showLoading(msg, parm) {
149
+ let _parm = parm || {}
155
150
  loadingObj = ElLoading.service({
151
+ // 默认配置
156
152
  lock: true,
157
- text: msg || '加载中...',
153
+ text: '加载中...',
158
154
  spinner: 'el-icon-loading',
159
- background: 'rgba(0, 0, 0, 0.7)'
155
+ background: 'rgba(0, 0, 0, 0.7)',
156
+ // 展开 _parm,其属性会覆盖上面的默认配置
157
+ ..._parm
160
158
  })
161
159
  }
162
160