@ecan-bi/tools 1.0.62 → 1.0.64

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.
@@ -0,0 +1,472 @@
1
+ import { unref } from 'vue'
2
+ import useVariablesInText from '../../hooks/useVariablesInText'
3
+ import useValueFormatter from '../../hooks/useValueFormatter'
4
+ import runCode from '../runCode'
5
+ export const getFieldConfig = (props, graphicConfig) => {
6
+ let dataFieldNames = props.dataFieldNames
7
+ if (graphicConfig) {
8
+ const { formFields = {} } = graphicConfig
9
+ if (formFields?.labelField && formFields?.valueField) {
10
+ dataFieldNames = {
11
+ name: formFields.labelField,
12
+ value: formFields.valueField
13
+ }
14
+ }
15
+ }
16
+ return dataFieldNames
17
+ }
18
+ // 设置坐标轴最大最小值
19
+ export const setAxisExtremum = (echartRef) => {
20
+ const _yExtent = echartRef.chart.getModel().getComponent('yAxis').axis.scale._extent
21
+ const _xExtent = echartRef.chart.getModel().getComponent('xAxis').axis.scale._extent
22
+ let obj = {}
23
+ if (_xExtent && _yExtent) {
24
+ obj = {
25
+ xAxisMinValue: _xExtent[0],
26
+ xAxisMaxValue: _xExtent[1],
27
+ yAxisMinValue: _yExtent[0],
28
+ yAxisMaxValue: _yExtent[1]
29
+ }
30
+ }
31
+ return obj
32
+ }
33
+ // 获取平均数
34
+ function getAverage(arr: any) {
35
+ if (!Array.isArray(arr) || arr.length === 0) return 0
36
+ const sum = arr.reduce((total, num) => total + num, 0)
37
+ return sum / arr.length
38
+ }
39
+ // 获取中位数
40
+ function getMedian(arr: any) {
41
+ if (!Array.isArray(arr) || arr.length === 0) {
42
+ return 0
43
+ }
44
+ const sortedArr = [...arr].sort((a, b) => a - b)
45
+ const len = sortedArr.length
46
+ const mid = Math.floor(len / 2)
47
+ if (len % 2 !== 0) {
48
+ return sortedArr[mid]
49
+ }
50
+ return (sortedArr[mid - 1] + sortedArr[mid]) / 2
51
+ }
52
+ function setCoord(unit: any, key: string, value: string | number) {
53
+ switch (key) {
54
+ case 'startX':
55
+ unit[0].coord[0] = +value
56
+ break
57
+ case 'startY':
58
+ unit[0].coord[1] = +value
59
+ break
60
+ case 'endX':
61
+ unit[1].coord[0] = +value
62
+ break
63
+ case 'endY':
64
+ unit[1].coord[1] = +value
65
+ break
66
+ default:
67
+ break
68
+ }
69
+ }
70
+ export const getParamValue = (type: string, axisItem: any, dataset: any) => {
71
+ let result = 0
72
+ let values = []
73
+ if (axisItem.x) {
74
+ values = unref(dataset).map((v: any) => v.value[0])
75
+ } else if (axisItem.y) {
76
+ values = unref(dataset).map((v: any) => v.value[1])
77
+ }
78
+ switch (type) {
79
+ case 'max':
80
+ result = Math.max(...values)
81
+ break
82
+ case 'min':
83
+ result = Math.min(...values)
84
+ break
85
+ case 'average':
86
+ result = getAverage(values)
87
+ break
88
+ case 'median':
89
+ result = getMedian(values)
90
+ break
91
+ default:
92
+ break
93
+ }
94
+ return result
95
+ }
96
+ const areaValueMap: any = {
97
+ 最大值: '{max}',
98
+ 最小值: '{min}',
99
+ 平均值: '{average}',
100
+ 中位数: '{median}'
101
+ }
102
+ // 图表标线
103
+ const markLineData = (props, maxValueObj, dataset, componentValues) => {
104
+ const { xAxisMarkLineValue = [], yAxisMarkLineValue = [] } = props
105
+ const { xAxisMinValue, xAxisMaxValue, yAxisMinValue, yAxisMaxValue } = maxValueObj
106
+ const xList: { [key: string]: any }[] = xAxisMarkLineValue.map((v) => ({ ...v, x: true }))
107
+ const yList: { [key: string]: any }[] = yAxisMarkLineValue.map((v) => ({ ...v, y: true }))
108
+ const axisList = xList.concat(yList)
109
+ if (axisList?.length) {
110
+ const result = []
111
+ for (const item of axisList) {
112
+ const commonParams: any = {
113
+ label: {
114
+ show: true,
115
+ formatter: '',
116
+ rich: {
117
+ ft: {}
118
+ }
119
+ }
120
+ }
121
+ const lineStyle: any = {}
122
+ let expressStr = item.value
123
+ const variables = expressStr?.match(/\{(.+?)\}/g)
124
+ let axisStr = ''
125
+ // 文本
126
+ commonParams.label.formatter = item.label ? `{ft|${item.label}}` : ''
127
+ // 偏移量
128
+ if (item.offsetHorizontal || item.offsetVertical) {
129
+ if (item.x) {
130
+ commonParams.label.rich.ft.padding = [0, item.offsetHorizontal || 0, item.offsetVertical || 0, 0]
131
+ } else if (item.y) {
132
+ commonParams.label.rich.ft.padding = [item.offsetVertical || 0, 0, 0, item.offsetHorizontal || 0]
133
+ }
134
+ }
135
+ // 文本颜色
136
+ if (item.labelColor) {
137
+ commonParams.label.rich.ft.color = item.labelColor
138
+ }
139
+ // 线条颜色
140
+ if (item.lineColor) {
141
+ lineStyle.color = item.lineColor
142
+ }
143
+ // 线条类型
144
+ if (item.lineType) {
145
+ lineStyle.type = item.lineType
146
+ }
147
+ if (item.x) {
148
+ axisStr = 'xAxis'
149
+ } else if (item.y) {
150
+ axisStr = 'yAxis'
151
+ }
152
+ if (variables?.length) {
153
+ for (const variable of variables) {
154
+ expressStr = expressStr.replace(variable, variable.slice(1, -1))
155
+ }
156
+ if (expressStr) {
157
+ let resultValue: any
158
+ if (componentValues && componentValues.value[expressStr]) {
159
+ // 组件值
160
+ resultValue = unref(componentValues)[expressStr]
161
+ } else {
162
+ // 坐标轴最大最小值
163
+ console.log('0000000', expressStr)
164
+ resultValue = runCode(expressStr, {
165
+ axisMax: item.x ? unref(xAxisMaxValue) : item.y ? unref(yAxisMaxValue) : 0,
166
+ axisMin: item.x ? unref(xAxisMinValue) : item.y ? unref(yAxisMinValue) : 0,
167
+ max: getParamValue('max', item, dataset),
168
+ min: getParamValue('min', item, dataset),
169
+ average: getParamValue('average', item, dataset),
170
+ median: getParamValue('median', item, dataset)
171
+ })
172
+ }
173
+ if (!isNaN(+resultValue)) {
174
+ result.push({
175
+ [axisStr]: +resultValue,
176
+ lineStyle,
177
+ ...commonParams
178
+ })
179
+ }
180
+ }
181
+ } else if (!isNaN(+item.value)) {
182
+ result.push({
183
+ [axisStr]: item.value,
184
+ lineStyle,
185
+ ...commonParams
186
+ })
187
+ }
188
+ }
189
+ return {
190
+ symbol: ['none', 'none'],
191
+ data: result
192
+ }
193
+ } else {
194
+ return {
195
+ data: []
196
+ }
197
+ }
198
+ }
199
+ const markAreaData = (props, maxValueObj, dataset) => {
200
+ const { axisMarkArea = [] } = props
201
+ const { xAxisMinValue, xAxisMaxValue, yAxisMinValue, yAxisMaxValue } = maxValueObj
202
+ if (axisMarkArea?.length) {
203
+ const result = []
204
+ for (const item of axisMarkArea) {
205
+ const unit = [
206
+ {
207
+ name: item.label || '',
208
+ coord: [],
209
+ itemStyle: {
210
+ color: item.color || 'transparent'
211
+ },
212
+ label: {
213
+ show: !!item.label,
214
+ position: 'inside',
215
+ fontSize: 16,
216
+ color: '#000'
217
+ }
218
+ },
219
+ {
220
+ coord: []
221
+ }
222
+ ]
223
+ for (const key in item) {
224
+ if (['startX', 'startY', 'endX', 'endY'].includes(key)) {
225
+ let expressStr = areaValueMap[item[key]] || item[key]
226
+ const variables = expressStr?.match(/\{(.+?)\}/g)
227
+ if (variables?.length) {
228
+ for (const variable of variables) {
229
+ expressStr = expressStr.replace(variable, variable.slice(1, -1))
230
+ }
231
+ if (expressStr) {
232
+ const xyFlag = {
233
+ x: key.includes('X'),
234
+ y: key.includes('Y')
235
+ }
236
+ const usedVariable = runCode(expressStr, {
237
+ xMax: unref(xAxisMaxValue),
238
+ xMin: unref(xAxisMinValue),
239
+ yMax: unref(yAxisMaxValue),
240
+ yMin: unref(yAxisMinValue),
241
+ max: getParamValue('max', xyFlag, dataset),
242
+ min: getParamValue('min', xyFlag, dataset),
243
+ average: getParamValue('average', xyFlag, dataset),
244
+ median: getParamValue('median', xyFlag, dataset)
245
+ })
246
+ if (!isNaN(+usedVariable)) {
247
+ setCoord(unit, key, usedVariable)
248
+ }
249
+ }
250
+ } else if (!isNaN(+item[key])) {
251
+ setCoord(unit, key, item[key])
252
+ }
253
+ }
254
+ }
255
+ if (unit.every((v) => v.coord?.length)) {
256
+ result.push(unit)
257
+ }
258
+ }
259
+ return {
260
+ data: result
261
+ }
262
+ } else {
263
+ return {
264
+ data: []
265
+ }
266
+ }
267
+ }
268
+
269
+ export default function getScatterTransformProps(props, dataset, fontSize, graphicConfig, maxValueObj, fontFamily, componentValues) {
270
+ console.log(fontFamily)
271
+ const fieldConfig = getFieldConfig(props, graphicConfig)
272
+ // 这样写为了触发响应式
273
+ // 返回函数中使用无法触发
274
+ const xAxisLabelFormatter = props.xAxisLabelFormatter
275
+ const yAxisLabelFormatter = props.yAxisLabelFormatter
276
+ const markLine = maxValueObj ? markLineData(props, maxValueObj, dataset, componentValues) : undefined
277
+ const markArea = maxValueObj ? markAreaData(props, maxValueObj, dataset) : undefined
278
+ return {
279
+ xAxis: {
280
+ z: 5,
281
+ // type: 'value'
282
+ splitLine: {
283
+ show: props.xAxisSplitLineShow,
284
+ lineStyle: {
285
+ color: props.xAxisSplitLineStyleColor
286
+ },
287
+ interval: props.xAxisSplitLineInterval
288
+ },
289
+ splitArea: {
290
+ show: props.xAxisSplitAreaShow
291
+ },
292
+ axisLabel: {
293
+ show: props.xAxisLabelShow,
294
+ fontSize: props.xAxisLabelFontSize,
295
+ color: props.xAxisLabelColor,
296
+ interval: props.xAxisLabelInterval || 0,
297
+ rotate: props.xAxisLabelRotate,
298
+ width: props.xAxisLabelWidth,
299
+ overflow: props.xAxisLabelOverflow,
300
+ formatter(value: string) {
301
+ if (typeof value === 'string' && value[0] === '0' && !isNaN(+value)) {
302
+ value = (+value).toString()
303
+ }
304
+ return useValueFormatter(xAxisLabelFormatter, value)
305
+ }
306
+ },
307
+ axisLine: {
308
+ lineStyle: {
309
+ color: props.xAxisLineStyleColor
310
+ },
311
+ symbol: ['none', props.showXAxisLineArrow ? 'arrow' : 'none'],
312
+ symbolSize: [8, 12],
313
+ onZero: false
314
+ },
315
+ axisTick: {
316
+ show: props.xAxisTickShow
317
+ },
318
+ name: props.xAxisName,
319
+ nameLocation: props.xAxisLineInverse ? 'start' : 'end',
320
+ nameTextStyle: {
321
+ fontSize: props.xAxisLabelFontSize,
322
+ color: props.xAxisLabelColor,
323
+ align: 'left'
324
+ },
325
+ inverse: props.xAxisLineInverse,
326
+ max: props.xAxisMax,
327
+ min: props.xAxisMin
328
+ },
329
+ yAxis: {
330
+ z: 5,
331
+ splitLine: {
332
+ show: props.yAxisSplitLineShow,
333
+ lineStyle: {
334
+ color: props.yAxisSplitLineStyleColor,
335
+ type: props.yAxisSplitLineType
336
+ }
337
+ },
338
+ axisTick: {
339
+ show: props.yAxisTickShow
340
+ },
341
+ splitArea: {
342
+ show: props.yAxisSplitAreaShow
343
+ },
344
+ axisLabel: {
345
+ show: props.yAxisLabelShow,
346
+ fontSize: props.yAxisLabelFontSize,
347
+ color: props.yAxisLabelColor,
348
+ formatter(value: string) {
349
+ return useValueFormatter(yAxisLabelFormatter, value)
350
+ }
351
+ },
352
+ axisLine: {
353
+ show: props.yAxisLineAlwaysDisplay,
354
+ lineStyle: {
355
+ color: props.yAxisLineStyleColor
356
+ },
357
+ symbol: ['none', props.showYAxisLineArrow ? 'arrow' : 'none'],
358
+ symbolSize: [8, 12],
359
+ onZero: false
360
+ },
361
+ name: props.yAxisName,
362
+ nameLocation: props.yAxisLineInverse ? 'start' : 'end',
363
+ nameTextStyle: {
364
+ fontSize: props.yAxisLabelFontSize,
365
+ color: props.yAxisLabelColor,
366
+ align: 'right'
367
+ },
368
+ inverse: props.yAxisLineInverse,
369
+ max: props.yAxisMax,
370
+ min: props.yAxisMin
371
+ },
372
+ // 提示
373
+ tooltip: {
374
+ show: props.tooltipShow,
375
+ trigger: props.tooltipTrigger,
376
+ formatter(params) {
377
+ const { marker, seriesName, componentType } = params
378
+ const record = params?.data?.record ?? {}
379
+ const name = record[fieldConfig.name]
380
+ const value = record[fieldConfig.value]
381
+ if (['markLine', 'markArea'].includes(componentType)) {
382
+ return ''
383
+ } else {
384
+ return useVariablesInText(
385
+ props.tooltipFormatter,
386
+ {
387
+ textData: {
388
+ marker,
389
+ seriesName,
390
+ a: seriesName,
391
+ b: name,
392
+ c: value,
393
+ ...record
394
+ }
395
+ },
396
+ {
397
+ useNewline: true,
398
+ useSpace: true
399
+ }
400
+ )
401
+ }
402
+ },
403
+ axisPointer: {
404
+ type: props.crossShow || props.crossShow === undefined ? 'cross' : ''
405
+ },
406
+ textStyle: {
407
+ fontSize: unref(fontSize)
408
+ },
409
+ position: props.tooltipPosition || undefined
410
+ },
411
+ // 图例
412
+ legend: {
413
+ show: props.legendShow,
414
+ orient: props.legendOrient,
415
+ top: props.legendTop,
416
+ left: props.legendLeft,
417
+ textStyle: {
418
+ color: props.legendTextStyleColor,
419
+ fontSize
420
+ }
421
+ },
422
+ series: [
423
+ {
424
+ data: unref(dataset),
425
+ type: 'scatter',
426
+ symbolSize: props.symbolSize,
427
+ itemStyle: {
428
+ color: props.symbolColor
429
+ },
430
+ label: {
431
+ show: props.labelShow,
432
+ fontSize: props.labelFontSize,
433
+ position: props.labelPosition,
434
+ color: props.labelColor,
435
+ width: props.labelWidth,
436
+ overflow: props.labelOverflow,
437
+ formatter: (params: any) => {
438
+ let formatter = ''
439
+ let labelFormatter = props.labelFormatter
440
+ if (labelFormatter === '') {
441
+ labelFormatter = '{c}'
442
+ }
443
+ const { seriesName, data } = params || {}
444
+ const record = data?.record ?? {}
445
+ const name = record[fieldConfig.name]
446
+ const value = record[fieldConfig.value]
447
+ formatter += useVariablesInText(
448
+ labelFormatter,
449
+ {
450
+ textData: {
451
+ name,
452
+ value,
453
+ a: seriesName,
454
+ b: name,
455
+ c: value || 0,
456
+ ...record
457
+ }
458
+ },
459
+ {
460
+ useNewline: true,
461
+ useSpace: true
462
+ }
463
+ )
464
+ return formatter
465
+ }
466
+ },
467
+ markLine,
468
+ markArea
469
+ }
470
+ ]
471
+ }
472
+ }