lw-cdp-ui 1.4.28 → 1.4.29

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, 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>
@@ -57,49 +78,38 @@ export default {
57
78
  type: String,
58
79
  default: '300px'
59
80
  },
60
- subtitle: {type: String, default: '同比变化'},
61
- tooltip: {type: String, default: ''}
81
+ subtitle: { type: String, default: '同比变化' },
82
+ tooltip: { type: String, default: '' }
62
83
  },
63
84
  computed: {
64
85
  parsedData() {
65
- const {setting, dataSet} = this.rawData
66
- const {tables} = dataSet
86
+ const { setting, dataSet } = this.rawData
87
+ const { tables } = dataSet
67
88
 
68
- const visibleTables = tables.filter(table => setting?.displayMetrics?.includes(`${table.name}.${table.metricId}`))
69
-
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
- })
89
+ const visibleTables = setting?.displayMetrics
90
+ ?.map((metric) => {
91
+ const [tableName, metricId] = metric.split('.')
92
+ return tables.find((table) => table.name === tableName && table.metricId === metricId)
92
93
  })
93
- })
94
- return result
94
+ .filter(Boolean)
95
+
96
+ return this.transformData(visibleTables, setting)
95
97
  },
96
98
  columns() {
97
99
  return this.parsedData?.length < this.rawData.setting.columnCount
98
100
  ? this.parsedData?.length
99
101
  : this.rawData.setting.columnCount
100
102
  },
103
+ paddingDefault() {
104
+ return [
105
+ `${this.rawData.setting?.grid?.top}px` || 0,
106
+ `${this.rawData.setting?.grid?.right}px` || 0,
107
+ `${this.rawData.setting?.grid?.bottom}px` || 0,
108
+ `${this.rawData.setting?.grid?.left}px` || 0
109
+ ]
110
+ },
101
111
  titleLeftRight() {
102
- let {left} = this.rawData.setting?.title || {}
112
+ let { left } = this.rawData.setting?.title || {}
103
113
  let params = {}
104
114
  if (left == 'left') {
105
115
  params.left = 0
@@ -113,30 +123,65 @@ export default {
113
123
  return params
114
124
  },
115
125
  legendLeftRight() {
116
- let {left, top} = this.rawData.setting?.legend || {}
126
+ let { left, top } = this.rawData.setting?.legend || {}
117
127
  let params = {}
118
128
  if (left == 'left') {
119
- params.left = 0
120
- params.right = 'auto'
129
+ params['justify-content'] = 'flex-start'
121
130
  } else if (left == 'center') {
122
- params.right = '50%'
123
- params.transform = 'translateX(50%)'
131
+ params['justify-content'] = 'center'
124
132
  } else {
125
- params.left = 'auto'
126
- params.right = 0
133
+ params['justify-content'] = 'flex-end'
127
134
  }
128
135
 
129
136
  if (top == 'top') {
130
- params.top = 0
137
+ params['align-items'] = 'flex-start'
131
138
  } else if (top == 'bottom') {
132
- params.bottom = 0
139
+ params['align-items'] = 'flex-end'
133
140
  } else if (top == 'middle') {
134
- params.top = '50%'
135
- params.transform = 'translateY(-50%)'
141
+ params['align-items'] = 'center'
136
142
  }
137
143
 
138
144
  return params
139
145
  }
146
+ },
147
+ methods: {
148
+ transformData(tables, setting) {
149
+ const result = []
150
+
151
+ // 1. 找出最长的headers长度(决定最终要循环多少次)
152
+ const maxHeadersLength = Math.max(...tables.map((table) => table.headers.length))
153
+
154
+ // 2. 遍历每个位置(0到maxHeadersLength-1)
155
+ for (let i = 0; i < maxHeadersLength; i++) {
156
+ const positionGroup = []
157
+
158
+ // 3. 遍历每个table,获取第i个header和对应的value
159
+ tables.forEach((table) => {
160
+ // 如果当前table的headers长度不够,跳过或用默认值
161
+ if (i < table.headers.length) {
162
+ const header = table.headers[i]
163
+ const metricName = table.metricName
164
+ const value = table.rows[0].values[i]
165
+
166
+ positionGroup.push({
167
+ name: header != metricName ? `${header}-${metricName}` : metricName,
168
+ unit: table.unit,
169
+ unitName: table.unitName,
170
+ unit: table.unit,
171
+ setting,
172
+ value: value
173
+ })
174
+ }
175
+ })
176
+
177
+ // 4. 将当前position的数据组加入结果
178
+ if (positionGroup.length > 0) {
179
+ result.push(positionGroup)
180
+ }
181
+ }
182
+
183
+ return result
184
+ }
140
185
  }
141
186
  }
142
187
  </script>
@@ -156,9 +201,6 @@ export default {
156
201
  // max-width: 300px;
157
202
  width: 100%;
158
203
  min-width: 30%;
159
- display: flex;
160
- flex-direction: column;
161
- justify-content: space-between;
162
204
  background-color: var(--el-bg-color-overlay);
163
205
  box-shadow: 0 0 30px rgba(0, 0, 0, 0.0509803922);
164
206
  position: relative;
@@ -169,8 +211,9 @@ export default {
169
211
  }
170
212
  .statistic-current {
171
213
  font-size: 17px;
172
- position: absolute;
173
- right: 0;
214
+ display: flex;
215
+ align-items: flex-start;
216
+ justify-content: flex-end;
174
217
  }
175
218
 
176
219
  .statistic-footer {
@@ -180,7 +223,8 @@ export default {
180
223
  flex-wrap: wrap;
181
224
  font-size: 12px;
182
225
  color: var(--el-text-color-regular);
183
- margin-top: 16px;
226
+ margin-top: 5px;
227
+ position: absolute;
184
228
  }
185
229
 
186
230
  .statistic-footer .footer-item {
@@ -201,5 +245,17 @@ export default {
201
245
  .red {
202
246
  color: var(--el-color-error);
203
247
  }
248
+
249
+ .statistic-item {
250
+ display: flex;
251
+ justify-content: space-between;
252
+ align-items: center;
253
+ font-size: 12px;
254
+ color: var(--el-text-color-placeholder);
255
+ .number {
256
+ color: var(--el-text-color-primary);
257
+ margin-left: 2px;
258
+ }
259
+ }
204
260
  }
205
261
  </style>