lw-cdp-ui 1.4.28 → 1.4.30

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.
@@ -1,45 +1,66 @@
1
1
  <template>
2
- <div class="chart-title-card-list"
3
- :style="{gridTemplateColumns: `repeat(${columns || 1}, 1fr)`}">
4
- <div v-for="(item, index) in parsedData"
5
- :key="index"
6
- class="chart-title-card"
7
- :style="{ height,textAlign: item.setting?.title?.left || 'left' }">
8
- <div class="title-top"
9
- :style="{ textAlign: item.setting?.title?.left || 'left', padding: item.setting?.title?.padding?.map(num => num + 'px').join(' ') || 0 }"
10
- v-if="item.setting.title?.show">
11
- <span :style="{
12
- color: item.setting.title?.textStyle?.color || item.color,
13
- fontWeight: item.setting.title?.textStyle?.fontWeight || 'normal',
14
- fontSize: item.setting.title?.textStyle?.fontSize + 'px' || '17px' }">{{ item.title }}</span>
15
- <el-tooltip v-if="item.tooltip"
16
- effect="dark"
17
- :content="item.tooltip"
18
- placement="top">
19
- <el-icon class="icon-tooltip"><el-icon-warning /></el-icon>
20
- </el-tooltip>
21
- </div>
22
- <div class="statistic-current"
23
- :style="{
24
- ...legendLeftRight,
25
- color: item.setting.legend?.textStyle?.color || item.color,
26
- padding: item.setting?.legend?.padding?.map(num => num + 'px').join(' ') || 0,
27
- fontWeight: item.setting.legend?.textStyle?.fontWeight || 'bold',
28
- fontSize: item.setting.legend?.textStyle?.fontSize + 'px' || '17px'}">
29
- {{ item.current?.toLocaleString('en-US') }}
30
- </div>
31
-
32
- <div v-if="parsedData.length > 1"
33
- class="statistic-footer">
34
- <span>{{ item.subtitle }}</span>
35
- <div :style="{ color: item.percentage >= 0 ? '#BF1220' : '#00B78B' }">
36
- <el-icon v-if="item.percentage >= 0"
37
- class="icon-up"><el-icon-top /></el-icon>
38
- <el-icon v-else
39
- class="icon-down"><el-icon-bottom /></el-icon>
40
- {{ Math.abs(item.percentage) }}%
41
- </div>
42
- </div>
2
+ <div class="chart-title-card-list" :style="{ gridTemplateColumns: `repeat(${columns || 1}, 1fr)` }">
3
+ <div
4
+ v-for="(parsedItem, parsedIndex) in parsedData"
5
+ :key="parsedIndex"
6
+ class="chart-title-card"
7
+ :style="{ height: cardHeight, padding: paddingDefault }">
8
+ <template v-for="(item, index) in parsedItem" :key="item.name">
9
+ <template v-if="index === 0">
10
+ <div>
11
+ <div
12
+ class="title-top"
13
+ :style="{
14
+ textAlign: item.setting?.title?.left || 'left',
15
+ padding: item.setting?.title?.padding?.map((num) => num + 'px').join(' ') || 0
16
+ }"
17
+ v-if="item.setting.title?.show">
18
+ <span
19
+ :style="{
20
+ color: item.setting.title?.textStyle?.color || item.color,
21
+ fontWeight: item.setting.title?.textStyle?.fontWeight || 'normal',
22
+ fontSize: item.setting.title?.textStyle?.fontSize + 'px' || '17px'
23
+ }"
24
+ >{{ item.name }}</span
25
+ >
26
+ <el-tooltip v-if="item.tooltip" effect="dark" :content="item.tooltip" placement="top">
27
+ <el-icon class="icon-tooltip"><el-icon-warning /></el-icon>
28
+ </el-tooltip>
29
+ </div>
30
+ <div
31
+ class="statistic-current"
32
+ :style="{
33
+ ...legendLeftRight,
34
+ color: item.setting.legend?.textStyle?.color || item.color,
35
+ padding: item.setting?.legend?.padding?.map((num) => num + 'px').join(' ') || 0,
36
+ fontWeight: item.setting.legend?.textStyle?.fontWeight || 'bold',
37
+ fontSize: item.setting.legend?.textStyle?.fontSize + 'px' || '17px'
38
+ }">
39
+ {{ item.value?.toLocaleString('en-US') }}
40
+ </div>
41
+ </div>
42
+ </template>
43
+ <template v-else-if="index == parsedItem.length - 1">
44
+ <div
45
+ class="statistic-footer"
46
+ :style="{
47
+ left: rawData.setting?.grid?.left + 'px',
48
+ bottom: rawData.setting?.grid?.bottom + 'px',
49
+ right: rawData.setting?.grid?.right + 'px'
50
+ }">
51
+ <span>{{ item.name }}</span>
52
+ <div :style="{ color: item.value >= 0 ? '#BF1220' : '#00B78B' }">
53
+ {{ Math.abs(item.value) }} {{ item.unitName }}
54
+ </div>
55
+ </div>
56
+ </template>
57
+ <template v-else>
58
+ <div class="statistic-item">
59
+ <span>{{ item.name }}</span>
60
+ <div class="number">{{ Math.abs(item.value) }} {{ item.unitName }}</div>
61
+ </div>
62
+ </template>
63
+ </template>
43
64
  </div>
44
65
  </div>
45
66
  </template>
@@ -47,6 +68,11 @@
47
68
  <script>
48
69
  export default {
49
70
  name: 'MetricCard',
71
+ data() {
72
+ return {
73
+ cardHeight: 0
74
+ }
75
+ },
50
76
  props: {
51
77
  rawData: {
52
78
  type: Object,
@@ -55,51 +81,47 @@ export default {
55
81
  },
56
82
  height: {
57
83
  type: String,
58
- default: '300px'
84
+ default: ''
59
85
  },
60
- subtitle: {type: String, default: '同比变化'},
61
- tooltip: {type: String, default: ''}
86
+ subtitle: { type: String, default: '同比变化' },
87
+ tooltip: { type: String, default: '' }
62
88
  },
63
89
  computed: {
64
90
  parsedData() {
65
- const {setting, dataSet} = this.rawData
66
- const {tables} = dataSet
67
-
68
- const visibleTables = tables.filter(table => setting?.displayMetrics?.includes(`${table.name}.${table.metricId}`))
91
+ const { setting, dataSet } = this.rawData
92
+ const { tables } = dataSet
69
93
 
70
- const result = []
71
- visibleTables.forEach((table, index) => {
72
- table.headers.forEach((x, xIndex) => {
73
- result.push({
74
- title: `${setting?.title?.text || table.metricName} ${table?.unitName ? `(${table.unitName})` : ''}`,
75
- index: x,
76
- color: setting.color[xIndex],
77
- subtitle: '环比上期',
78
- current: table.rows[0]?.values[xIndex],
79
- tooltip: table.name,
80
- percentage:
81
- xIndex > 1
82
- ? table.rows[0]?.values[xIndex] == 0
83
- ? 0
84
- : Math.round(
85
- ((table.rows[0]?.values[xIndex] - table.rows[0]?.values[xIndex - 1]) /
86
- table.rows[0]?.values[xIndex - 1]) *
87
- 10000
88
- ) / 100
89
- : 0,
90
- setting
91
- })
94
+ const visibleTables = setting?.displayMetrics
95
+ ?.map((metric) => {
96
+ const [tableName, metricId] = metric.split('.')
97
+ return tables.find((table) => table.name === tableName && table.metricId === metricId)
92
98
  })
93
- })
94
- return result
99
+ .filter(Boolean)
100
+
101
+ // 处理处理高度
102
+ if (!this.height) {
103
+ this.cardHeight = 200 + (visibleTables.length - 2) * 10 + 'px'
104
+ } else {
105
+ this.cardHeight = this.height
106
+ }
107
+
108
+ return this.transformData(visibleTables, setting)
95
109
  },
96
110
  columns() {
97
111
  return this.parsedData?.length < this.rawData.setting.columnCount
98
112
  ? this.parsedData?.length
99
113
  : this.rawData.setting.columnCount
100
114
  },
115
+ paddingDefault() {
116
+ return [
117
+ `${this.rawData.setting?.grid?.top}px` || 0,
118
+ `${this.rawData.setting?.grid?.right}px` || 0,
119
+ `${this.rawData.setting?.grid?.bottom}px` || 0,
120
+ `${this.rawData.setting?.grid?.left}px` || 0
121
+ ]
122
+ },
101
123
  titleLeftRight() {
102
- let {left} = this.rawData.setting?.title || {}
124
+ let { left } = this.rawData.setting?.title || {}
103
125
  let params = {}
104
126
  if (left == 'left') {
105
127
  params.left = 0
@@ -113,30 +135,65 @@ export default {
113
135
  return params
114
136
  },
115
137
  legendLeftRight() {
116
- let {left, top} = this.rawData.setting?.legend || {}
138
+ let { left, top } = this.rawData.setting?.legend || {}
117
139
  let params = {}
118
140
  if (left == 'left') {
119
- params.left = 0
120
- params.right = 'auto'
141
+ params['justify-content'] = 'flex-start'
121
142
  } else if (left == 'center') {
122
- params.right = '50%'
123
- params.transform = 'translateX(50%)'
143
+ params['justify-content'] = 'center'
124
144
  } else {
125
- params.left = 'auto'
126
- params.right = 0
145
+ params['justify-content'] = 'flex-end'
127
146
  }
128
147
 
129
148
  if (top == 'top') {
130
- params.top = 0
149
+ params['align-items'] = 'flex-start'
131
150
  } else if (top == 'bottom') {
132
- params.bottom = 0
151
+ params['align-items'] = 'flex-end'
133
152
  } else if (top == 'middle') {
134
- params.top = '50%'
135
- params.transform = 'translateY(-50%)'
153
+ params['align-items'] = 'center'
136
154
  }
137
155
 
138
156
  return params
139
157
  }
158
+ },
159
+ methods: {
160
+ transformData(tables, setting) {
161
+ const result = []
162
+
163
+ // 1. 找出最长的headers长度(决定最终要循环多少次)
164
+ const maxHeadersLength = Math.max(...tables.map((table) => table.headers.length))
165
+
166
+ // 2. 遍历每个位置(0到maxHeadersLength-1)
167
+ for (let i = 0; i < maxHeadersLength; i++) {
168
+ const positionGroup = []
169
+
170
+ // 3. 遍历每个table,获取第i个header和对应的value
171
+ tables.forEach((table) => {
172
+ // 如果当前table的headers长度不够,跳过或用默认值
173
+ if (i < table.headers.length) {
174
+ const header = table.headers[i]
175
+ const metricName = table.metricName
176
+ const value = table.rows[0].values[i]
177
+
178
+ positionGroup.push({
179
+ name: header != metricName ? `${header}-${metricName}` : metricName,
180
+ unit: table.unit,
181
+ unitName: table.unitName,
182
+ unit: table.unit,
183
+ setting,
184
+ value: value
185
+ })
186
+ }
187
+ })
188
+
189
+ // 4. 将当前position的数据组加入结果
190
+ if (positionGroup.length > 0) {
191
+ result.push(positionGroup)
192
+ }
193
+ }
194
+
195
+ return result
196
+ }
140
197
  }
141
198
  }
142
199
  </script>
@@ -156,9 +213,6 @@ export default {
156
213
  // max-width: 300px;
157
214
  width: 100%;
158
215
  min-width: 30%;
159
- display: flex;
160
- flex-direction: column;
161
- justify-content: space-between;
162
216
  background-color: var(--el-bg-color-overlay);
163
217
  box-shadow: 0 0 30px rgba(0, 0, 0, 0.0509803922);
164
218
  position: relative;
@@ -169,8 +223,9 @@ export default {
169
223
  }
170
224
  .statistic-current {
171
225
  font-size: 17px;
172
- position: absolute;
173
- right: 0;
226
+ display: flex;
227
+ align-items: flex-start;
228
+ justify-content: flex-end;
174
229
  }
175
230
 
176
231
  .statistic-footer {
@@ -180,7 +235,8 @@ export default {
180
235
  flex-wrap: wrap;
181
236
  font-size: 12px;
182
237
  color: var(--el-text-color-regular);
183
- margin-top: 16px;
238
+ margin-top: 5px;
239
+ position: absolute;
184
240
  }
185
241
 
186
242
  .statistic-footer .footer-item {
@@ -201,5 +257,17 @@ export default {
201
257
  .red {
202
258
  color: var(--el-color-error);
203
259
  }
260
+
261
+ .statistic-item {
262
+ display: flex;
263
+ justify-content: space-between;
264
+ align-items: center;
265
+ font-size: 12px;
266
+ color: var(--el-text-color-placeholder);
267
+ .number {
268
+ color: var(--el-text-color-primary);
269
+ margin-left: 2px;
270
+ }
271
+ }
204
272
  }
205
273
  </style>