@agions/taroviz 1.3.1 → 1.6.0

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.
Files changed (64) hide show
  1. package/README.md +4 -4
  2. package/dist/cjs/index.js +1 -1
  3. package/dist/esm/index.js +3814 -2724
  4. package/package.json +1 -1
  5. package/src/__tests__/integration.test.tsx +12 -10
  6. package/src/adapters/BaseAdapter.ts +116 -0
  7. package/src/adapters/__tests__/index.test.ts +10 -10
  8. package/src/adapters/index.ts +63 -74
  9. package/src/adapters/swan/index.ts +26 -223
  10. package/src/adapters/tt/index.ts +28 -225
  11. package/src/adapters/types.ts +36 -0
  12. package/src/adapters/weapp/index.ts +29 -189
  13. package/src/charts/bar/index.tsx +5 -9
  14. package/src/charts/boxplot/__tests__/index.test.tsx +130 -0
  15. package/src/charts/boxplot/index.tsx +18 -0
  16. package/src/charts/boxplot/types.ts +46 -0
  17. package/src/charts/candlestick/__tests__/index.test.tsx +37 -0
  18. package/src/charts/candlestick/index.tsx +13 -0
  19. package/src/charts/common/BaseChartWrapper.tsx +47 -38
  20. package/src/charts/funnel/index.tsx +5 -9
  21. package/src/charts/gauge/index.tsx +5 -9
  22. package/src/charts/graph/__tests__/index.test.tsx +41 -0
  23. package/src/charts/graph/index.tsx +13 -0
  24. package/src/charts/heatmap/index.tsx +5 -9
  25. package/src/charts/index.ts +10 -1
  26. package/src/charts/line/index.tsx +4 -7
  27. package/src/charts/parallel/__tests__/index.test.tsx +164 -0
  28. package/src/charts/parallel/index.tsx +18 -0
  29. package/src/charts/parallel/types.ts +73 -0
  30. package/src/charts/pie/index.tsx +5 -10
  31. package/src/charts/radar/index.tsx +5 -9
  32. package/src/charts/scatter/index.tsx +5 -9
  33. package/src/charts/types.ts +48 -4
  34. package/src/charts/wordcloud/__tests__/index.test.tsx +36 -0
  35. package/src/charts/wordcloud/index.tsx +13 -0
  36. package/src/core/animation/AnimationManager.ts +15 -0
  37. package/src/core/components/Annotation.tsx +26 -21
  38. package/src/core/components/BaseChart.tsx +280 -1105
  39. package/src/core/components/ErrorBoundary.tsx +4 -1
  40. package/src/core/components/LazyChart.tsx +42 -55
  41. package/src/core/components/hooks/index.ts +20 -0
  42. package/src/core/components/hooks/useChartEvents.ts +143 -0
  43. package/src/core/components/hooks/useChartInit.ts +80 -0
  44. package/src/core/components/hooks/usePerformance.ts +186 -0
  45. package/src/core/components/hooks/useVirtualScroll.ts +156 -0
  46. package/src/core/echarts.ts +1 -1
  47. package/src/core/themes/ThemeManager.ts +31 -15
  48. package/src/core/types/index.ts +2 -2
  49. package/src/core/utils/chartInstances.ts +10 -3
  50. package/src/core/utils/chartUtils.ts +46 -0
  51. package/src/core/utils/common.ts +14 -1
  52. package/src/core/utils/export/ExportUtils.ts +13 -22
  53. package/src/core/utils/performance/PerformanceAnalyzer.ts +32 -5
  54. package/src/core/utils/uuid.ts +1 -1
  55. package/src/editor/EnhancedThemeEditor.tsx +624 -0
  56. package/src/editor/ThemeEditor.tsx +1 -6
  57. package/src/hooks/__tests__/index.test.tsx +14 -11
  58. package/src/hooks/__tests__/useDataTransform.test.ts +159 -0
  59. package/src/hooks/index.ts +54 -19
  60. package/src/hooks/useDataTransform.ts +503 -0
  61. package/src/index.ts +27 -9
  62. package/src/main.tsx +4 -4
  63. package/src/themes/__tests__/index.test.ts +2 -2
  64. package/src/themes/index.ts +13 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ import React from 'react';
5
+ import { render, screen } from '@testing-library/react';
6
+ import '@testing-library/jest-dom';
7
+ import ParallelChart from '../index';
8
+
9
+ // Mock ECharts and adapters
10
+ jest.mock('echarts/core', () => ({
11
+ use: jest.fn(),
12
+ init: jest.fn(() => ({
13
+ setOption: jest.fn(),
14
+ showLoading: jest.fn(),
15
+ hideLoading: jest.fn(),
16
+ on: jest.fn(),
17
+ off: jest.fn(),
18
+ dispose: jest.fn(),
19
+ resize: jest.fn(),
20
+ })),
21
+ getInstanceByDom: jest.fn(),
22
+ }));
23
+
24
+ // Mock ECharts components
25
+ jest.mock('echarts/components', () => ({
26
+ GridComponent: jest.fn(),
27
+ TooltipComponent: jest.fn(),
28
+ TitleComponent: jest.fn(),
29
+ LegendComponent: jest.fn(),
30
+ }));
31
+
32
+ // Mock BaseChartWrapper
33
+ jest.mock('../../common/BaseChartWrapper', () => ({
34
+ __esModule: true,
35
+ default: (props: any) => (
36
+ <div
37
+ data-testid="parallel-chart"
38
+ className={`taroviz-parallel ${props.className || ''}`}
39
+ style={{ width: props.width || '100%', height: props.height || 300, ...props.style }}
40
+ >
41
+ <div data-testid="chart-option">{JSON.stringify(props.option)}</div>
42
+ </div>
43
+ ),
44
+ }));
45
+
46
+ describe('ParallelChart', () => {
47
+ const basicOption = {
48
+ title: { text: '平行坐标图测试' },
49
+ parallel: {
50
+ left: '5%',
51
+ right: '10%',
52
+ bottom: '10%',
53
+ top: '20%',
54
+ height: '50%',
55
+ },
56
+ parallelAxisDefault: {
57
+ type: 'value' as const,
58
+ name: '指标',
59
+ },
60
+ series: [{
61
+ type: 'parallel' as const,
62
+ lineStyle: { width: 2, opacity: 0.5 },
63
+ data: [
64
+ [1, 55, 9, 56, 0.46, 2, 35],
65
+ [2, 25, 11, 21, 0.65, 2, 33],
66
+ [3, 56, 7, 63, 0.92, 3, 45],
67
+ ],
68
+ }],
69
+ };
70
+
71
+ describe('Basic Rendering', () => {
72
+ it('should render without crashing', () => {
73
+ render(<ParallelChart option={basicOption} />);
74
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
75
+ });
76
+
77
+ it('should render with custom width and height', () => {
78
+ render(<ParallelChart option={basicOption} width={600} height={500} />);
79
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
80
+ });
81
+
82
+ it('should have correct display name', () => {
83
+ expect(ParallelChart.displayName).toBe('ParallelChart');
84
+ });
85
+
86
+ it('should pass option to wrapper', () => {
87
+ render(<ParallelChart option={basicOption} />);
88
+ expect(screen.getByTestId('chart-option')).toHaveTextContent('平行坐标图测试');
89
+ });
90
+ });
91
+
92
+ describe('Props', () => {
93
+ it('should accept className prop', () => {
94
+ render(<ParallelChart option={basicOption} className="test-class" />);
95
+ expect(screen.getByTestId('parallel-chart')).toHaveClass('test-class');
96
+ });
97
+
98
+ it('should accept style prop', () => {
99
+ const style = { padding: '10px' };
100
+ render(<ParallelChart option={basicOption} style={style} />);
101
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
102
+ });
103
+
104
+ it('should accept loading prop', () => {
105
+ render(<ParallelChart option={basicOption} loading={true} />);
106
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
107
+ });
108
+
109
+ it('should accept theme prop', () => {
110
+ render(<ParallelChart option={basicOption} theme="dark" />);
111
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
112
+ });
113
+ });
114
+
115
+ describe('Chart Options', () => {
116
+ it('should render with expandable axis', () => {
117
+ const expandableOption = {
118
+ ...basicOption,
119
+ parallel: {
120
+ ...basicOption.parallel,
121
+ axisExpandable: true,
122
+ axisExpandCenter: 3,
123
+ axisExpandCount: 3,
124
+ },
125
+ };
126
+ render(<ParallelChart option={expandableOption} />);
127
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
128
+ });
129
+
130
+ it('should render with custom lineStyle', () => {
131
+ const customLineOption = {
132
+ ...basicOption,
133
+ series: [{
134
+ type: 'parallel' as const,
135
+ lineStyle: { width: 3, color: '#1890ff', opacity: 0.8 },
136
+ data: [[1, 55, 9, 56, 0.46, 2, 35]],
137
+ }],
138
+ };
139
+ render(<ParallelChart option={customLineOption} />);
140
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
141
+ });
142
+
143
+ it('should render with category axis', () => {
144
+ const categoryOption = {
145
+ title: { text: '分类轴测试' },
146
+ parallel: { left: '5%', right: '10%', bottom: '10%', top: '20%' },
147
+ parallelAxisDefault: {
148
+ type: 'category' as const,
149
+ data: ['A', 'B', 'C', 'D', 'E'],
150
+ name: '分类',
151
+ },
152
+ series: [{
153
+ type: 'parallel' as const,
154
+ data: [
155
+ ['A', 55, 9, 56, 0.46, 2, 35],
156
+ ['B', 25, 11, 21, 0.65, 2, 33],
157
+ ],
158
+ }],
159
+ };
160
+ render(<ParallelChart option={categoryOption} />);
161
+ expect(screen.getByTestId('parallel-chart')).toBeInTheDocument();
162
+ });
163
+ });
164
+ });
@@ -0,0 +1,18 @@
1
+ /**
2
+ * 平行坐标图组件
3
+ * 用于展示高维数据各维度之间的关系
4
+ */
5
+ import React, { memo } from 'react';
6
+ import BaseChartWrapper from '../common/BaseChartWrapper';
7
+ import { ParallelChartProps } from './types';
8
+
9
+ const ParallelChart: React.FC<ParallelChartProps> = memo((props) => (
10
+ <BaseChartWrapper {...props} chartType="parallel" />
11
+ ));
12
+
13
+ ParallelChart.displayName = 'ParallelChart';
14
+
15
+ export default ParallelChart;
16
+
17
+ // 导出类型
18
+ export type { ParallelChartProps, ParallelOption, ParallelAxisSetting } from './types';
@@ -0,0 +1,73 @@
1
+ /**
2
+ * 平行坐标图类型定义
3
+ */
4
+
5
+ export type ParallelChartProps = {
6
+ option?: ParallelOption;
7
+ width?: string | number;
8
+ height?: string | number;
9
+ className?: string;
10
+ style?: React.CSSProperties;
11
+ onEvents?: Record<string, (params: any) => void>;
12
+ loading?: boolean;
13
+ loadingOption?: any;
14
+ theme?: string;
15
+ onChartReady?: (chart: any) => void;
16
+ opts?: {
17
+ devicePixelRatio?: number;
18
+ renderer?: 'canvas' | 'svg';
19
+ };
20
+ };
21
+
22
+ export interface ParallelOption {
23
+ title?: any;
24
+ legend?: any;
25
+ parallel?: ParallelAxisSetting;
26
+ parallelAxisDefault?: ParallelAxisItem;
27
+ grid?: any;
28
+ tooltip?: any;
29
+ series: ParallelSeriesItem[];
30
+ dataset?: any;
31
+ color?: string[];
32
+ backgroundColor?: any;
33
+ textStyle?: any;
34
+ [key: string]: any;
35
+ }
36
+
37
+ export interface ParallelAxisSetting {
38
+ left?: number | string;
39
+ right?: number | string;
40
+ top?: number | string;
41
+ bottom?: number | string;
42
+ width?: number | string;
43
+ height?: number | string;
44
+ axisExpandable?: boolean;
45
+ axisExpandCenter?: number;
46
+ axisExpandCount?: number;
47
+ axisExpandWidth?: number;
48
+ z?: number;
49
+ }
50
+
51
+ export interface ParallelAxisItem {
52
+ type?: 'value' | 'category';
53
+ name?: string;
54
+ nameLocation?: 'start' | 'middle' | 'center' | 'end';
55
+ nameTextStyle?: any;
56
+ nameGap?: number;
57
+ silent?: boolean;
58
+ data?: any[];
59
+ dimension?: number;
60
+ parallelIndex?: number;
61
+ }
62
+
63
+ export interface ParallelSeriesItem {
64
+ type: 'parallel';
65
+ name?: string;
66
+ data?: any[];
67
+ lineStyle?: any;
68
+ emphasis?: any;
69
+ smooth?: boolean | number;
70
+ symbol?: string;
71
+ symbolSize?: number;
72
+ itemStyle?: any;
73
+ }
@@ -1,19 +1,14 @@
1
1
  /**
2
- * 饼图组件
2
+ * PieChart组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { BaseChartProps } from '../types';
8
-
9
- // 导入统一注册的 echarts
10
7
  import '@/core/echarts';
11
8
 
12
- /**
13
- * 饼图组件
14
- */
15
- const PieChart: React.FC<BaseChartProps> = (props) => (
9
+ const PieChart: React.FC<BaseChartProps> = memo((props) => (
16
10
  <BaseChartWrapper {...props} chartType="pie-chart" />
17
- );
11
+ ));
12
+ PieChart.displayName = 'PieChart';
18
13
 
19
14
  export default PieChart;
@@ -1,18 +1,14 @@
1
1
  /**
2
- * 雷达图组件
2
+ * RadarChart组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { RadarChartProps } from '../types';
8
-
9
7
  import '@/core/echarts';
10
8
 
11
- /**
12
- * 雷达图组件
13
- */
14
- const RadarChart: React.FC<RadarChartProps> = (props) => (
9
+ const RadarChart: React.FC<RadarChartProps> = memo((props) => (
15
10
  <BaseChartWrapper {...props} chartType="radar-chart" />
16
- );
11
+ ));
12
+ RadarChart.displayName = 'RadarChart';
17
13
 
18
14
  export default RadarChart;
@@ -1,18 +1,14 @@
1
1
  /**
2
- * 散点图组件
2
+ * ScatterChart组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { ScatterChartProps } from '../types';
8
-
9
7
  import '@/core/echarts';
10
8
 
11
- /**
12
- * 散点图组件
13
- */
14
- const ScatterChart: React.FC<ScatterChartProps> = (props) => (
9
+ const ScatterChart: React.FC<ScatterChartProps> = memo((props) => (
15
10
  <BaseChartWrapper {...props} chartType="scatter-chart" />
16
- );
11
+ ));
12
+ ScatterChart.displayName = 'ScatterChart';
17
13
 
18
14
  export default ScatterChart;
@@ -713,7 +713,7 @@ export interface SankeyChartProps extends BaseChartProps {
713
713
  * 箱线图属性
714
714
  * 用于展示数据的分布情况
715
715
  */
716
- export interface BoxplotChartProps extends BaseChartProps {
716
+ export interface BoxplotChartProps extends Omit<BaseChartProps, 'data'> {
717
717
  /** 图表类型 */
718
718
  type?: 'boxplot';
719
719
 
@@ -743,9 +743,9 @@ export interface BoxplotChartProps extends BaseChartProps {
743
743
  * K线图/股票图属性
744
744
  * 用于展示股票、外汇等金融数据
745
745
  */
746
- export interface CandlestickChartProps extends BaseChartProps {
746
+ export interface CandlestickChartProps extends Omit<BaseChartProps, 'data'> {
747
747
  /** K线数据数组,每项为 [open, close, lowest, highest] */
748
- data?: number[][];
748
+ candlestickData?: number[][];
749
749
 
750
750
  /** X轴数据 */
751
751
  xAxisData?: (string | number)[];
@@ -874,4 +874,48 @@ export interface ChartBuilderOptions<T extends BaseChartProps = BaseChartProps>
874
874
  }
875
875
 
876
876
  // 重新导出 ECharts 类型
877
- export type { EChartsOption, ECharts, EChartsCoreOption };
877
+ export type { EChartsOption, ECharts } from 'echarts';
878
+
879
+ // EChartsCoreOption 是 ECBasicOption 的别名
880
+ export type { ECBasicOption as EChartsCoreOption } from 'echarts/types/dist/shared';
881
+
882
+ /**
883
+ * 词云图属性
884
+ * 用于展示文本数据的词频分布
885
+ */
886
+ export interface WordCloudChartProps extends BaseChartProps {
887
+ /** 词云数据 - 也可以通过 option.series[0].data 传入 */
888
+ wordCloudData?: Array<{
889
+ name: string;
890
+ value: number;
891
+ textStyle?: Record<string, unknown>;
892
+ emphasis?: Record<string, unknown>;
893
+ }>;
894
+
895
+ /** 词云形状 */
896
+ shape?: 'circle' | 'cardioid' | 'diamond' | 'triangle' | 'star' | 'pentagon' | 'square';
897
+
898
+ /** 字体大小范围 */
899
+ sizeRange?: [number, number];
900
+
901
+ /** 词云旋转角度范围 */
902
+ rotationRange?: [number, number];
903
+
904
+ /** 旋转步长 */
905
+ rotationStep?: number;
906
+
907
+ /** 词云间距 */
908
+ gridSize?: number;
909
+
910
+ /** 是否绘制词云轮廓 */
911
+ drawOutOfBound?: boolean;
912
+
913
+ /** 文字样式 */
914
+ textStyle?: Record<string, unknown>;
915
+
916
+ /** 强调状态 */
917
+ emphasis?: {
918
+ focus?: 'self' | 'adjacency';
919
+ textStyle?: Record<string, unknown>;
920
+ };
921
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @version v1.5.0
3
+ */
4
+
5
+ import React from 'react';
6
+ import { render } from '@testing-library/react';
7
+ import WordCloudChart from '../index';
8
+
9
+ describe('WordCloudChart', () => {
10
+ it('renders without crashing', () => {
11
+ const { container } = render(<WordCloudChart />);
12
+ expect(container).toBeTruthy();
13
+ });
14
+
15
+ it('renders with custom width and height', () => {
16
+ const { container } = render(<WordCloudChart width={600} height={400} />);
17
+ expect(container.firstChild).toHaveStyle({ width: '600px', height: '400px' });
18
+ });
19
+
20
+ it('renders with word data', () => {
21
+ const option = {
22
+ series: [
23
+ {
24
+ type: 'wordCloud' as const,
25
+ data: [
26
+ { name: 'JavaScript', value: 10000 },
27
+ { name: 'TypeScript', value: 8000 },
28
+ { name: 'React', value: 6000 },
29
+ ],
30
+ },
31
+ ],
32
+ } as any;
33
+ const { container } = render(<WordCloudChart option={option} />);
34
+ expect(container).toBeTruthy();
35
+ });
36
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * WordCloudChart组件
3
+ */
4
+ import React, { memo } from 'react';
5
+ import BaseChartWrapper from '../common/BaseChartWrapper';
6
+ import { WordCloudChartProps } from '../types';
7
+
8
+ const WordCloudChart: React.FC<WordCloudChartProps> = memo((props) => (
9
+ <BaseChartWrapper {...props} chartType="wordcloud-chart" />
10
+ ));
11
+ WordCloudChart.displayName = 'WordCloudChart';
12
+
13
+ export default WordCloudChart;
@@ -141,6 +141,9 @@ export class AnimationManager {
141
141
  public static getInstance(config?: AnimationManagerConfig): AnimationManager {
142
142
  if (!AnimationManager.instance) {
143
143
  AnimationManager.instance = new AnimationManager(config);
144
+ } else if (config) {
145
+ // 如果传入了新配置,更新配置
146
+ AnimationManager.instance.updateConfig(config);
144
147
  }
145
148
  return AnimationManager.instance;
146
149
  }
@@ -345,6 +348,18 @@ export class AnimationManager {
345
348
  };
346
349
  }
347
350
 
351
+ /**
352
+ * 更新配置
353
+ */
354
+ public updateConfig(config: AnimationManagerConfig): void {
355
+ if (config.defaultConfig) {
356
+ this.defaultConfig = config.defaultConfig;
357
+ }
358
+ if (config.performance) {
359
+ this.updatePerformanceConfig(config.performance);
360
+ }
361
+ }
362
+
348
363
  /**
349
364
  * 获取性能配置
350
365
  */
@@ -2,7 +2,7 @@
2
2
  * TaroViz 图表标注组件
3
3
  * 支持在图表上添加标记线、标记区域、散点等标注
4
4
  */
5
- import React, { useMemo } from 'react';
5
+ import { useMemo } from 'react';
6
6
  import type { EChartsOption } from 'echarts';
7
7
 
8
8
  /**
@@ -209,7 +209,9 @@ export function convertAnnotationToMarkArea(config: MarkAreaConfig): EChartsOpti
209
209
  /**
210
210
  * 将散点标注配置转换为 ECharts 格式
211
211
  */
212
- export function convertAnnotationToScatter(config: ScatterAnnotationConfig): EChartsOption['series'] {
212
+ export function convertAnnotationToScatter(
213
+ config: ScatterAnnotationConfig
214
+ ): EChartsOption['series'] {
213
215
  const { data, symbol, symbolSize, itemStyle, label } = config;
214
216
 
215
217
  return [
@@ -227,7 +229,7 @@ export function convertAnnotationToScatter(config: ScatterAnnotationConfig): ECh
227
229
  },
228
230
  data,
229
231
  },
230
- },
232
+ } as any,
231
233
  ];
232
234
  }
233
235
 
@@ -239,18 +241,22 @@ export function useAnnotation(props: AnnotationProps): EChartsOption {
239
241
  const { type, markLine, markArea, scatter } = props;
240
242
 
241
243
  return useMemo(() => {
242
- const series: EChartsOption['series'] = [];
244
+ // 使用 any 避免类型复杂性问题
245
+ const series: any[] = [];
243
246
 
244
247
  if (type === 'line' && markLine) {
245
- series.push(...convertAnnotationToMarkLine(markLine));
248
+ const markLineResult = convertAnnotationToMarkLine(markLine);
249
+ series.push(...(Array.isArray(markLineResult) ? markLineResult : [markLineResult]));
246
250
  }
247
251
 
248
252
  if (type === 'area' && markArea) {
249
- series.push(...convertAnnotationToMarkArea(markArea));
253
+ const markAreaResult = convertAnnotationToMarkArea(markArea);
254
+ series.push(...(Array.isArray(markAreaResult) ? markAreaResult : [markAreaResult]));
250
255
  }
251
256
 
252
257
  if (type === 'scatter' && scatter) {
253
- series.push(...convertAnnotationToScatter(scatter));
258
+ const scatterResult = convertAnnotationToScatter(scatter);
259
+ series.push(...(Array.isArray(scatterResult) ? scatterResult : [scatterResult]));
254
260
  }
255
261
 
256
262
  return { series };
@@ -263,46 +269,42 @@ export function useAnnotation(props: AnnotationProps): EChartsOption {
263
269
  export const AnnotationPresets = {
264
270
  /** 平均线 */
265
271
  averageLine: (color = '#1890ff'): MarkLineConfig => ({
266
- data: [{ type: 'average', name: '平均值' }],
272
+ data: [{ type: 'average', name: '平均值' }] as any,
267
273
  lineStyle: { color, type: 'dashed', width: 2 },
268
274
  label: { show: true, position: 'end', color },
269
275
  }),
270
276
 
271
277
  /** 最大值线 */
272
278
  maxLine: (color = '#f5222d'): MarkLineConfig => ({
273
- data: [{ type: 'max', name: '最大值' }],
279
+ data: [{ type: 'max', name: '最大值' }] as any,
274
280
  lineStyle: { color, type: 'dashed', width: 2 },
275
281
  label: { show: true, position: 'end', color },
276
282
  }),
277
283
 
278
284
  /** 最小值线 */
279
285
  minLine: (color = '#52c41a'): MarkLineConfig => ({
280
- data: [{ type: 'min', name: '最小值' }],
286
+ data: [{ type: 'min', name: '最小值' }] as any,
281
287
  lineStyle: { color, type: 'dashed', width: 2 },
282
288
  label: { show: true, position: 'end', color },
283
289
  }),
284
290
 
285
291
  /** 警戒线 */
286
292
  thresholdLine: (value: number, color = '#faad14'): MarkLineConfig => ({
287
- data: [{ yAxis: value, name: '警戒线' }],
293
+ data: [{ yAxis: value, name: '警戒线' }] as any,
288
294
  lineStyle: { color, type: 'solid', width: 2 },
289
295
  label: { show: true, position: 'start', color },
290
296
  }),
291
297
 
292
298
  /** 目标区域 */
293
299
  targetArea: (min: number, max: number, color = 'rgba(82, 196, 26, 0.1)'): MarkAreaConfig => ({
294
- data: [
295
- [{ yAxis: min }, { yAxis: max }],
296
- ],
300
+ data: [[{ yAxis: min }, { yAxis: max }]],
297
301
  style: { color, opacity: 0.3 },
298
302
  label: { show: true, position: 'inside', color: '#52c41a' },
299
303
  }),
300
304
 
301
305
  /** 预警区域 */
302
306
  warningArea: (min: number, max: number, color = 'rgba(250, 173, 20, 0.1)'): MarkAreaConfig => ({
303
- data: [
304
- [{ yAxis: min }, { yAxis: max }],
305
- ],
307
+ data: [[{ yAxis: min }, { yAxis: max }]],
306
308
  style: { color, opacity: 0.3 },
307
309
  label: { show: true, position: 'inside', color: '#faad14' },
308
310
  }),
@@ -319,17 +321,20 @@ export function createCompositeAnnotation(
319
321
  scatter?: ScatterAnnotationConfig;
320
322
  }>
321
323
  ): EChartsOption {
322
- const allSeries: EChartsOption['series'] = [];
324
+ const allSeries: any[] = [];
323
325
 
324
326
  annotations.forEach((annotation) => {
325
327
  if (annotation.type === 'line' && annotation.markLine) {
326
- allSeries.push(...convertAnnotationToMarkLine(annotation.markLine));
328
+ const result = convertAnnotationToMarkLine(annotation.markLine);
329
+ allSeries.push(...(Array.isArray(result) ? result : [result]));
327
330
  }
328
331
  if (annotation.type === 'area' && annotation.markArea) {
329
- allSeries.push(...convertAnnotationToMarkArea(annotation.markArea));
332
+ const result = convertAnnotationToMarkArea(annotation.markArea);
333
+ allSeries.push(...(Array.isArray(result) ? result : [result]));
330
334
  }
331
335
  if (annotation.type === 'scatter' && annotation.scatter) {
332
- allSeries.push(...convertAnnotationToScatter(annotation.scatter));
336
+ const result = convertAnnotationToScatter(annotation.scatter);
337
+ allSeries.push(...(Array.isArray(result) ? result : [result]));
333
338
  }
334
339
  });
335
340