lambo-design-bi 0.0.233 → 0.0.234

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,7 +1,8 @@
1
1
  <template>
2
2
  <LamboNumberInfoBi :title="title" :sub-title="subTitle" :num="num" :sub-num1="subNum1" :trend1="trend1"
3
3
  :widget="widget" :is-drill="isDrill" @on-drill="onDrill" :sub-num2="subNum2" :trend2="trend2" :polar1="polar1"
4
- :polar2="polar2" :eva-level="evaLevel" :tab-clickable="tabClickable" :default-tab-active="defaultTabActive" @on-tab-click="onTabClick">
4
+ :polar2="polar2" :eva-level="evaLevel" :tab-clickable="tabClickable" :default-tab-active="defaultTabActive"
5
+ :show-trend-chart="isTrendCharts" :trend-chart-data="trendChartsData" @on-tab-click="onTabClick">
5
6
  </LamboNumberInfoBi>
6
7
  </template>
7
8
  <script>
@@ -46,7 +47,9 @@ export default {
46
47
  drillV3: null,
47
48
  evaLevel: null,
48
49
  tabClickable: false,
49
- defaultTabActive: false
50
+ defaultTabActive: false,
51
+ isTrendCharts: false,
52
+ trendChartsData: []
50
53
  }
51
54
  },
52
55
  methods: {
@@ -65,6 +68,29 @@ export default {
65
68
  console.log("num-info initConfig 卡片初始设置为激活状态触发点击,START 当前实例:", this.widget.id + "_" + this.widget.name + ",defaultTabActive:" + this.widget.options["defaultTabActive"])
66
69
  this.defaultTabActive = true
67
70
  }
71
+ this.isTrendCharts = this.widget.options.isTrendCharts === true || this.widget.options.isTrendCharts === '1'
72
+ },
73
+ parseTrendChartsValue(value) {
74
+ if (Array.isArray(value)) {
75
+ return value
76
+ }
77
+ if (typeof value === 'string') {
78
+ const trimValue = value.trim()
79
+ if (trimValue.indexOf('[') === 0 && trimValue.lastIndexOf(']') === trimValue.length - 1) {
80
+ try {
81
+ const parseValue = JSON.parse(trimValue)
82
+ if (Array.isArray(parseValue)) {
83
+ return parseValue
84
+ }
85
+ } catch (e) {
86
+ console.log("BiNumIndex -- parseTrendChartsValue -- 字符串数组解析失败:", {
87
+ value,
88
+ error: e
89
+ })
90
+ }
91
+ }
92
+ }
93
+ return []
68
94
  },
69
95
  doSearch() {
70
96
  if (!this.apiId) {
@@ -75,6 +101,7 @@ export default {
75
101
  if (res.data.code === 0) {
76
102
  console.error("数据卡片的调用服务[" + this.widget.options.apiId + "]失败:" + res.data.message)
77
103
  } else {
104
+ this.trendChartsData = []
78
105
  if (res.data.data.rows.length > 0) {
79
106
  let row = res.data.data.rows[0]
80
107
  if (row) {
@@ -105,6 +132,9 @@ export default {
105
132
  if (Object.prototype.hasOwnProperty.call(row, 'eva_level')) {
106
133
  this.evaLevel = row['eva_level'] || ''
107
134
  }
135
+ if (this.isTrendCharts) {
136
+ this.trendChartsData = this.parseTrendChartsValue(row['trendChartsData'])
137
+ }
108
138
  }
109
139
  }
110
140
  }
@@ -356,7 +356,8 @@ export default {
356
356
  display: 'block',
357
357
  margin: '0',
358
358
  width: width + 'px',
359
- height: height + 'px'
359
+ height: height + 'px',
360
+ opacity: 0.62
360
361
  },
361
362
  hook: {
362
363
  insert: vnode => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lambo-design-bi",
3
- "version": "0.0.233",
3
+ "version": "0.0.234",
4
4
  "description": "Vue2 BI 数据可视化组件库",
5
5
  "main": "index.js",
6
6
  "author": "finch",
@@ -21,40 +21,45 @@
21
21
  <div v-if="subTitle" class="ivu-number-info-subTitle">
22
22
  <slot name="subTitle">{{ subTitle }}</slot>
23
23
  </div>
24
- <div class="ivu-number-info-value-lambo" :style="valueStyle">
25
- <span class="ivu-number-info-total">
26
- <slot name="num">{{ num }}</slot>
27
- </span>
28
- <span class="ivu-number-info-subTotal" v-if="subNum1 || subNum2">
29
- <slot name="subNum">
30
- <template v-if="subNum1">
31
- <template v-if="trend1">
32
- <template v-if="polar1 === 'pos'">
33
- <Trend :flag="trend1" text-color reverse-color>{{ subNum1 }}</Trend>
24
+ <div class="number-info-content" :class="{ 'has-trend-chart': hasTrendChart }">
25
+ <div v-if="hasTrendChart" class="number-info-trend-chart-bg">
26
+ <canvas ref="trendCanvas"></canvas>
27
+ </div>
28
+ <div class="ivu-number-info-value-lambo" :style="valueStyle">
29
+ <span class="ivu-number-info-total">
30
+ <slot name="num">{{ num }}</slot>
31
+ </span>
32
+ <span class="ivu-number-info-subTotal" v-if="subNum1 || subNum2">
33
+ <slot name="subNum">
34
+ <template v-if="subNum1">
35
+ <template v-if="trend1">
36
+ <template v-if="polar1 === 'pos'">
37
+ <Trend :flag="trend1" text-color reverse-color>{{ subNum1 }}</Trend>
38
+ </template>
39
+ <template v-else>
40
+ <Trend :flag="trend1" text-color>{{ subNum1 }}</Trend>
41
+ </template>
34
42
  </template>
35
43
  <template v-else>
36
- <Trend :flag="trend1" text-color>{{ subNum1 }}</Trend>
44
+ {{ subNum1 }}
37
45
  </template>
38
46
  </template>
39
- <template v-else>
40
- {{ subNum1 }}
41
- </template>
42
- </template>
43
- <template v-if="subNum2">
44
- <template v-if="trend2">
45
- <template v-if="polar2 === 'pos'">
46
- <Trend :flag="trend2" text-color reverse-color>{{ subNum2 }}</Trend>
47
+ <template v-if="subNum2">
48
+ <template v-if="trend2">
49
+ <template v-if="polar2 === 'pos'">
50
+ <Trend :flag="trend2" text-color reverse-color>{{ subNum2 }}</Trend>
51
+ </template>
52
+ <template v-else>
53
+ <Trend :flag="trend2" text-color>{{ subNum2 }}</Trend>
54
+ </template>
47
55
  </template>
48
56
  <template v-else>
49
- <Trend :flag="trend2" text-color>{{ subNum2 }}</Trend>
57
+ {{ subNum2 }}
50
58
  </template>
51
59
  </template>
52
- <template v-else>
53
- {{ subNum2 }}
54
- </template>
55
- </template>
56
- </slot>
57
- </span>
60
+ </slot>
61
+ </span>
62
+ </div>
58
63
  </div>
59
64
  <div class="card-bottom-line" :class="{ 'active': isActive }"></div>
60
65
  </div>
@@ -129,6 +134,14 @@ export default {
129
134
  type: Boolean,
130
135
  default: false
131
136
  },
137
+ showTrendChart: {
138
+ type: Boolean,
139
+ default: false
140
+ },
141
+ trendChartData: {
142
+ type: Array,
143
+ default: () => []
144
+ },
132
145
  widget: {
133
146
  type: Object,
134
147
  default: () => ({})
@@ -139,6 +152,9 @@ export default {
139
152
  return {
140
153
  'margin-top': this.gap + 'px'
141
154
  };
155
+ },
156
+ hasTrendChart() {
157
+ return this.showTrendChart && this.trendChartData && this.trendChartData.length > 0
142
158
  }
143
159
  },
144
160
  data() {
@@ -189,6 +205,85 @@ export default {
189
205
  }
190
206
  console.log("num-info handleCardClick 卡片初始设置为激活状态触发点击,END 当前实例:", this.widget.id + "_" + this.widget.name)
191
207
  }
208
+ },
209
+ drawTrendChart() {
210
+ const canvas = this.$refs.trendCanvas
211
+ if (!canvas) return
212
+
213
+ const width = canvas.clientWidth || 160
214
+ const height = canvas.clientHeight || 64
215
+ const data = this.trendChartData.map(item => Number(item))
216
+ const ctx = canvas.getContext('2d')
217
+ const ratio = window.devicePixelRatio || 1
218
+ canvas.width = width * ratio
219
+ canvas.height = height * ratio
220
+ canvas.style.width = width + 'px'
221
+ canvas.style.height = height + 'px'
222
+ ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
223
+ ctx.clearRect(0, 0, width, height)
224
+ if (!data.length || data.some(item => isNaN(item))) {
225
+ return
226
+ }
227
+
228
+ const padding = { top: 5, right: 6, bottom: 5, left: 6 }
229
+ const chartW = width - padding.left - padding.right
230
+ const chartH = height - padding.top - padding.bottom
231
+ const dataMax = Math.max(...data)
232
+ const dataMin = Math.min(...data)
233
+ const dataRange = dataMax - dataMin || 1
234
+ const max = dataMax + dataRange * 0.04
235
+ const min = dataMin - dataRange * 0.04
236
+ const range = max - min || 1
237
+ const points = data.map((val, index) => ({
238
+ x: data.length === 1 ? width / 2 : padding.left + (index / (data.length - 1)) * chartW,
239
+ y: padding.top + chartH - ((val - min) / range) * chartH
240
+ }))
241
+
242
+ const gradient = ctx.createLinearGradient(0, padding.top, 0, height)
243
+ gradient.addColorStop(0, 'rgba(45, 140, 240, 0.32)')
244
+ gradient.addColorStop(0.55, 'rgba(45, 140, 240, 0.12)')
245
+ gradient.addColorStop(1, 'rgba(45, 140, 240, 0.03)')
246
+
247
+ ctx.beginPath()
248
+ ctx.moveTo(points[0].x, height - padding.bottom)
249
+ points.forEach((point, index) => {
250
+ if (index === 0) {
251
+ ctx.lineTo(point.x, point.y)
252
+ } else {
253
+ const prevPoint = points[index - 1]
254
+ const midX = (prevPoint.x + point.x) / 2
255
+ ctx.bezierCurveTo(midX, prevPoint.y, midX, point.y, point.x, point.y)
256
+ }
257
+ })
258
+ ctx.lineTo(points[points.length - 1].x, height - padding.bottom)
259
+ ctx.closePath()
260
+ ctx.fillStyle = gradient
261
+ ctx.fill()
262
+
263
+ ctx.beginPath()
264
+ points.forEach((point, index) => {
265
+ if (index === 0) {
266
+ ctx.moveTo(point.x, point.y)
267
+ } else {
268
+ const prevPoint = points[index - 1]
269
+ const midX = (prevPoint.x + point.x) / 2
270
+ ctx.bezierCurveTo(midX, prevPoint.y, midX, point.y, point.x, point.y)
271
+ }
272
+ })
273
+ ctx.strokeStyle = '#2d8cf0'
274
+ ctx.lineWidth = 1.8
275
+ ctx.lineJoin = 'round'
276
+ ctx.lineCap = 'round'
277
+ ctx.stroke()
278
+
279
+ const lastPoint = points[points.length - 1]
280
+ ctx.beginPath()
281
+ ctx.arc(lastPoint.x, lastPoint.y, 3, 0, Math.PI * 2)
282
+ ctx.fillStyle = 'rgba(45, 140, 240, 0.18)'
283
+ ctx.fill()
284
+ ctx.strokeStyle = '#2d8cf0'
285
+ ctx.lineWidth = 1.5
286
+ ctx.stroke()
192
287
  }
193
288
  },
194
289
  created() {
@@ -196,13 +291,62 @@ export default {
196
291
  },
197
292
  mounted() {
198
293
  this.initDefTabClickActiveStatus()
294
+ this.$nextTick(() => {
295
+ if (this.hasTrendChart) {
296
+ this.drawTrendChart()
297
+ }
298
+ })
199
299
  },
200
300
  beforeDestroy() {
201
301
  this.eventBusOff()
302
+ },
303
+ watch: {
304
+ trendChartData() {
305
+ this.$nextTick(() => {
306
+ if (this.hasTrendChart) {
307
+ this.drawTrendChart()
308
+ }
309
+ })
310
+ },
311
+ showTrendChart() {
312
+ this.$nextTick(() => {
313
+ if (this.hasTrendChart) {
314
+ this.drawTrendChart()
315
+ }
316
+ })
317
+ }
202
318
  }
203
319
  };
204
320
  </script>
205
321
  <style scoped lang="less">
322
+ .number-info-content.has-trend-chart {
323
+ position: relative;
324
+ min-height: 64px;
325
+ overflow: hidden;
326
+
327
+ .number-info-trend-chart-bg {
328
+ position: absolute;
329
+ right: -2px;
330
+ bottom: 0;
331
+ width: 65%;
332
+ height: 64px;
333
+ opacity: 0.62;
334
+ pointer-events: none;
335
+ z-index: 0;
336
+
337
+ canvas {
338
+ display: block;
339
+ width: 100%;
340
+ height: 64px;
341
+ }
342
+ }
343
+
344
+ .ivu-number-info-value-lambo {
345
+ position: relative;
346
+ z-index: 1;
347
+ }
348
+ }
349
+
206
350
  .ivu-number-info-value-lambo {
207
351
  font-family: var("DIN Alternate", "Roboto Mono", Menlo, Consolas, monospace);
208
352
  font-variant-numeric: tabular-nums;
@@ -214,6 +358,8 @@ export default {
214
358
  text-overflow: ellipsis;
215
359
  word-break: break-all;
216
360
  display: flex;
361
+ flex: 1;
362
+ min-width: 0;
217
363
  flex-direction: column;
218
364
  }
219
365