@agions/taroviz 1.3.0 → 1.5.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 (59) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/index.js +1 -1
  3. package/dist/esm/index.js +1827 -1547
  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/h5/index.ts +1 -3
  9. package/src/adapters/index.ts +65 -65
  10. package/src/adapters/swan/index.ts +26 -223
  11. package/src/adapters/tt/index.ts +28 -225
  12. package/src/adapters/types.ts +36 -0
  13. package/src/adapters/weapp/index.ts +29 -189
  14. package/src/charts/bar/index.tsx +5 -9
  15. package/src/charts/candlestick/__tests__/index.test.tsx +37 -0
  16. package/src/charts/candlestick/index.tsx +13 -0
  17. package/src/charts/common/BaseChartWrapper.tsx +49 -46
  18. package/src/charts/funnel/index.tsx +5 -9
  19. package/src/charts/gauge/index.tsx +5 -9
  20. package/src/charts/graph/__tests__/index.test.tsx +41 -0
  21. package/src/charts/graph/index.tsx +13 -0
  22. package/src/charts/heatmap/index.tsx +5 -9
  23. package/src/charts/index.ts +6 -1
  24. package/src/charts/line/index.tsx +4 -7
  25. package/src/charts/pie/index.tsx +5 -10
  26. package/src/charts/radar/index.tsx +5 -9
  27. package/src/charts/scatter/index.tsx +5 -9
  28. package/src/charts/types.ts +48 -4
  29. package/src/charts/wordcloud/__tests__/index.test.tsx +36 -0
  30. package/src/charts/wordcloud/index.tsx +13 -0
  31. package/src/core/animation/AnimationManager.ts +15 -0
  32. package/src/core/components/Annotation.tsx +26 -21
  33. package/src/core/components/BaseChart.tsx +280 -1105
  34. package/src/core/components/ErrorBoundary.tsx +4 -1
  35. package/src/core/components/LazyChart.tsx +42 -55
  36. package/src/core/components/hooks/index.ts +20 -0
  37. package/src/core/components/hooks/useChartEvents.ts +143 -0
  38. package/src/core/components/hooks/useChartInit.ts +80 -0
  39. package/src/core/components/hooks/usePerformance.ts +186 -0
  40. package/src/core/components/hooks/useVirtualScroll.ts +156 -0
  41. package/src/core/echarts.ts +1 -1
  42. package/src/core/themes/ThemeManager.ts +31 -15
  43. package/src/core/types/index.ts +2 -2
  44. package/src/core/utils/chartInstances.ts +18 -2
  45. package/src/core/utils/chartUtils.ts +46 -0
  46. package/src/core/utils/codeGenerator/CodeGenerator.ts +19 -5
  47. package/src/core/utils/common.ts +14 -1
  48. package/src/core/utils/export/ExportUtils.ts +13 -22
  49. package/src/core/utils/performance/PerformanceAnalyzer.ts +32 -5
  50. package/src/core/utils/uuid.ts +9 -5
  51. package/src/editor/ThemeEditor.tsx +1 -6
  52. package/src/hooks/__tests__/index.test.tsx +14 -11
  53. package/src/hooks/__tests__/useDataTransform.test.ts +159 -0
  54. package/src/hooks/index.ts +76 -23
  55. package/src/hooks/useDataTransform.ts +503 -0
  56. package/src/index.ts +15 -2
  57. package/src/main.tsx +4 -4
  58. package/src/themes/__tests__/index.test.ts +2 -2
  59. package/src/themes/index.ts +13 -0
@@ -2,13 +2,12 @@
2
2
  * 基础图表包装组件
3
3
  * 提供统一的图表初始化、渲染和生命周期管理
4
4
  */
5
- import * as echarts from 'echarts/core';
6
5
  import React, { useEffect, useRef, useMemo } from 'react';
7
6
 
8
7
  import { getAdapter } from '../../adapters';
9
8
  import { uuid } from '../../core/utils';
10
9
  import { BaseChartProps } from '../types';
11
- import { processAdapterConfig, safeRenderAdapter } from '../utils';
10
+ import { processAdapterConfig } from '../utils';
12
11
 
13
12
  /**
14
13
  * 基础图表包装组件
@@ -31,7 +30,7 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
31
30
  chartType = 'chart',
32
31
  }) => {
33
32
  const chartId = useRef<string>(`${chartType}-${uuid()}`);
34
- const chartInstance = useRef<echarts.ECharts | null>(null);
33
+ const chartInstance = useRef<any>(null);
35
34
  const containerRef = useRef<HTMLDivElement>(null);
36
35
 
37
36
  // 使用 useMemo 缓存适配器配置,并处理类型问题
@@ -46,56 +45,66 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
46
45
  renderer,
47
46
  option,
48
47
  });
49
- }, [width, height, theme, autoResize, renderer, option, chartType]);
48
+ }, [width, height, theme, autoResize, renderer, option]);
50
49
 
51
50
  // 处理图表初始化
52
51
  useEffect(() => {
53
- const initConfig = processAdapterConfig({
54
- ...adapterConfig,
55
- onInit: (instance: echarts.ECharts) => {
56
- chartInstance.current = instance;
57
-
58
- // 绑定事件
59
- if (onEvents) {
60
- Object.keys(onEvents).forEach((eventName) => {
61
- instance.on(eventName, onEvents[eventName]);
62
- });
63
- }
52
+ const initChart = async () => {
53
+ const initConfig = processAdapterConfig({
54
+ ...adapterConfig,
55
+ onInit: (instance: any) => {
56
+ chartInstance.current = instance;
64
57
 
65
- // 初始化回调
66
- if (onChartInit) {
67
- onChartInit(instance);
68
- }
58
+ // 绑定事件
59
+ if (onEvents) {
60
+ Object.keys(onEvents).forEach((eventName) => {
61
+ instance.on(eventName, (onEvents as any)[eventName]);
62
+ });
63
+ }
64
+
65
+ // 初始化回调
66
+ if (onChartInit) {
67
+ onChartInit(instance);
68
+ }
69
69
 
70
- // 准备好回调
71
- if (onChartReady) {
72
- onChartReady(instance);
70
+ // 准备好回调
71
+ if (onChartReady) {
72
+ onChartReady(instance);
73
+ }
74
+ },
75
+ });
76
+
77
+ // 获取适配器并初始化(异步动态导入)
78
+ const adapter = await getAdapter(initConfig);
79
+ adapter.init();
80
+
81
+ // 返回清理函数
82
+ return () => {
83
+ if (chartInstance.current) {
84
+ // 解绑事件
85
+ if (onEvents) {
86
+ Object.keys(onEvents).forEach((eventName) => {
87
+ chartInstance.current?.off(eventName);
88
+ });
89
+ }
90
+ chartInstance.current.dispose();
91
+ chartInstance.current = null;
73
92
  }
74
- },
75
- });
93
+ };
94
+ };
76
95
 
77
- // 获取适配器并初始化
78
- const adapter = getAdapter(initConfig);
79
- adapter.init();
96
+ // 执行异步初始化并获取清理函数
97
+ const cleanupPromise = initChart();
80
98
 
81
- // 组件卸载时清理
99
+ // 返回清理函数
82
100
  return () => {
83
- if (chartInstance.current) {
84
- // 解绑事件
85
- if (onEvents) {
86
- Object.keys(onEvents).forEach((eventName) => {
87
- chartInstance.current?.off(eventName);
88
- });
89
- }
90
- chartInstance.current.dispose();
91
- chartInstance.current = null;
92
- }
101
+ cleanupPromise.then((cleanup) => cleanup?.());
93
102
  };
94
103
  }, [adapterConfig, onChartInit, onChartReady, onEvents]);
95
104
 
96
105
  // 更新配置
97
106
  useEffect(() => {
98
- if (chartInstance.current) {
107
+ if (chartInstance.current && option) {
99
108
  chartInstance.current.setOption(option, true);
100
109
  }
101
110
  }, [option]);
@@ -118,18 +127,12 @@ const BaseChartWrapper: React.FC<BaseChartProps & { chartType: string }> = ({
118
127
  ...style,
119
128
  };
120
129
 
121
- // 使用带有处理的适配器配置创建适配器实例
122
- const adapter = getAdapter(adapterConfig);
123
-
124
130
  return (
125
131
  <div
126
132
  className={`taroviz-${chartType} ${className}`}
127
133
  style={mergedStyle}
128
134
  ref={containerRef as React.RefObject<HTMLDivElement>}
129
- >
130
- {/* 安全地渲染适配器 */}
131
- {safeRenderAdapter(adapter)}
132
- </div>
135
+ />
133
136
  );
134
137
  };
135
138
 
@@ -1,18 +1,14 @@
1
1
  /**
2
- * 漏斗图组件
2
+ * FunnelChart组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { FunnelChartProps } from '../types';
8
-
9
7
  import '@/core/echarts';
10
8
 
11
- /**
12
- * 漏斗图组件
13
- */
14
- const FunnelChart: React.FC<FunnelChartProps> = (props) => (
9
+ const FunnelChart: React.FC<FunnelChartProps> = memo((props) => (
15
10
  <BaseChartWrapper {...props} chartType="funnel-chart" />
16
- );
11
+ ));
12
+ FunnelChart.displayName = 'FunnelChart';
17
13
 
18
14
  export default FunnelChart;
@@ -1,18 +1,14 @@
1
1
  /**
2
- * 仪表盘组件
2
+ * GaugeChart组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { GaugeChartProps } from '../types';
8
-
9
7
  import '@/core/echarts';
10
8
 
11
- /**
12
- * 仪表盘组件
13
- */
14
- const GaugeChart: React.FC<GaugeChartProps> = (props) => (
9
+ const GaugeChart: React.FC<GaugeChartProps> = memo((props) => (
15
10
  <BaseChartWrapper {...props} chartType="gauge-chart" />
16
- );
11
+ ));
12
+ GaugeChart.displayName = 'GaugeChart';
17
13
 
18
14
  export default GaugeChart;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @version v1.5.0
3
+ */
4
+
5
+ import React from 'react';
6
+ import { render } from '@testing-library/react';
7
+ import GraphChart from '../index';
8
+
9
+ describe('GraphChart', () => {
10
+ it('renders without crashing', () => {
11
+ const { container } = render(<GraphChart />);
12
+ expect(container).toBeTruthy();
13
+ });
14
+
15
+ it('renders with custom className', () => {
16
+ const { container } = render(<GraphChart className="test-graph" />);
17
+ expect(container.firstChild).toHaveClass('test-graph');
18
+ });
19
+
20
+ it('renders with custom width and height', () => {
21
+ const { container } = render(<GraphChart width={500} height={400} />);
22
+ expect(container.firstChild).toHaveStyle({ width: '500px', height: '400px' });
23
+ });
24
+
25
+ it('renders with basic option', () => {
26
+ const option = {
27
+ series: [
28
+ {
29
+ type: 'graph' as const,
30
+ nodes: [
31
+ { id: '1', name: 'Node 1' },
32
+ { id: '2', name: 'Node 2' },
33
+ ],
34
+ links: [{ source: '1', target: '2' }],
35
+ },
36
+ ],
37
+ };
38
+ const { container } = render(<GraphChart option={option} />);
39
+ expect(container).toBeTruthy();
40
+ });
41
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * GraphChart组件
3
+ */
4
+ import React, { memo } from 'react';
5
+ import BaseChartWrapper from '../common/BaseChartWrapper';
6
+ import { GraphChartProps } from '../types';
7
+
8
+ const GraphChart: React.FC<GraphChartProps> = memo((props) => (
9
+ <BaseChartWrapper {...props} chartType="graph-chart" />
10
+ ));
11
+ GraphChart.displayName = 'GraphChart';
12
+
13
+ export default GraphChart;
@@ -1,18 +1,14 @@
1
1
  /**
2
- * 热力图组件
2
+ * HeatmapChart组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { HeatmapChartProps } from '../types';
8
-
9
7
  import '@/core/echarts';
10
8
 
11
- /**
12
- * 热力图组件
13
- */
14
- const HeatmapChart: React.FC<HeatmapChartProps> = (props) => (
9
+ const HeatmapChart: React.FC<HeatmapChartProps> = memo((props) => (
15
10
  <BaseChartWrapper {...props} chartType="heatmap-chart" />
16
- );
11
+ ));
12
+ HeatmapChart.displayName = 'HeatmapChart';
17
13
 
18
14
  export default HeatmapChart;
@@ -17,10 +17,15 @@ export { default as TreeMapChart } from './treemap';
17
17
  export { default as SunburstChart } from './sunburst';
18
18
  export { default as SankeyChart } from './sankey';
19
19
 
20
+ // 导出新增图表组件
21
+ export { default as GraphChart } from './graph';
22
+ export { default as CandlestickChart } from './candlestick';
23
+ export { default as WordCloudChart } from './wordcloud';
24
+
20
25
  // 导出类型定义
21
26
  export * from './types';
22
27
 
23
28
  /**
24
29
  * 版本信息
25
30
  */
26
- export const version = '1.2.1';
31
+ export const version = '1.4.0';
@@ -1,18 +1,15 @@
1
1
  /**
2
2
  * 折线图组件
3
3
  */
4
- import React from 'react';
5
-
4
+ import React, { memo } from 'react';
6
5
  import BaseChartWrapper from '../common/BaseChartWrapper';
7
6
  import { LineChartProps } from '../types';
8
7
 
9
8
  import '@/core/echarts';
10
9
 
11
- /**
12
- * 折线图组件
13
- */
14
- const LineChart: React.FC<LineChartProps> = (props) => (
10
+ const LineChart: React.FC<LineChartProps> = memo((props) => (
15
11
  <BaseChartWrapper {...props} chartType="line-chart" />
16
- );
12
+ ));
13
+ LineChart.displayName = 'LineChart';
17
14
 
18
15
  export default LineChart;
@@ -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