@agions/taroviz 1.11.1 → 2.0.3
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.
- package/CHANGELOG.md +245 -0
- package/README.md +104 -302
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/vendors.js +1 -0
- package/dist/cjs/vendors~echarts.js +1 -0
- package/dist/esm/index.js +1 -58151
- package/dist/esm/vendors.js +1 -0
- package/dist/esm/vendors~echarts.js +1 -0
- package/package.json +19 -25
- package/src/adapters/MiniAppAdapter.ts +136 -0
- package/src/adapters/__tests__/index.test.ts +1 -1
- package/src/adapters/h5/__tests__/index.test.ts +4 -2
- package/src/adapters/h5/index.ts +63 -64
- package/src/adapters/harmony/index.ts +23 -245
- package/src/adapters/index.ts +49 -45
- package/src/adapters/swan/index.ts +6 -69
- package/src/adapters/tt/index.ts +7 -70
- package/src/adapters/types.ts +25 -58
- package/src/adapters/weapp/index.ts +6 -69
- package/src/charts/__tests__/testUtils.tsx +87 -0
- package/src/charts/boxplot/__tests__/index.test.tsx +49 -103
- package/src/charts/boxplot/index.tsx +2 -1
- package/src/charts/boxplot/types.ts +17 -16
- package/src/charts/common/BaseChartWrapper.tsx +90 -82
- package/src/charts/common/__mocks__/BaseChartWrapper.tsx +17 -0
- package/src/charts/createChartComponent.tsx +36 -0
- package/src/charts/createOptionChartComponent.tsx +32 -0
- package/src/charts/funnel/__tests__/index.test.tsx +99 -0
- package/src/charts/funnel/index.tsx +60 -10
- package/src/charts/funnel/types.ts +6 -0
- package/src/charts/graph/__tests__/index.test.tsx +102 -33
- package/src/charts/graph/index.tsx +66 -9
- package/src/charts/graph/types.ts +6 -0
- package/src/charts/heatmap/__tests__/index.test.tsx +139 -0
- package/src/charts/heatmap/index.tsx +103 -10
- package/src/charts/heatmap/types.ts +6 -0
- package/src/charts/index.ts +74 -26
- package/src/charts/liquid/__tests__/index.test.tsx +52 -0
- package/src/charts/liquid/index.tsx +239 -182
- package/src/charts/liquid/types.ts +11 -11
- package/src/charts/parallel/__tests__/index.test.tsx +40 -67
- package/src/charts/parallel/index.tsx +2 -1
- package/src/charts/parallel/types.ts +19 -18
- package/src/charts/radar/__tests__/index.test.tsx +210 -0
- package/src/charts/radar/index.tsx +143 -10
- package/src/charts/radar/types.ts +13 -0
- package/src/charts/sankey/__tests__/index.test.tsx +124 -0
- package/src/charts/sankey/index.tsx +62 -10
- package/src/charts/sankey/types.ts +6 -0
- package/src/charts/tree/__tests__/index.test.tsx +71 -0
- package/src/charts/tree/index.tsx +5 -2
- package/src/charts/tree/types.ts +9 -9
- package/src/charts/types.ts +208 -106
- package/src/charts/utils.ts +9 -7
- package/src/charts/wordcloud/__tests__/index.test.tsx +98 -31
- package/src/charts/wordcloud/index.tsx +75 -9
- package/src/charts/wordcloud/types.ts +6 -0
- package/src/components/DataFilter/index.tsx +32 -10
- package/src/core/animation/types.ts +6 -6
- package/src/core/components/Annotation.tsx +6 -7
- package/src/core/components/BaseChart.tsx +110 -168
- package/src/core/components/ErrorBoundary.tsx +17 -4
- package/src/core/components/LazyChart.tsx +54 -55
- package/src/core/components/hooks/index.ts +6 -2
- package/src/core/components/hooks/useChartInit.ts +6 -3
- package/src/core/components/hooks/usePerformance.ts +8 -2
- package/src/core/components/hooks/useVirtualScroll.ts +2 -1
- package/src/core/index.ts +1 -1
- package/src/core/themes/ThemeManager.ts +1 -1
- package/src/core/types/common.ts +2 -1
- package/src/core/types/index.ts +0 -12
- package/src/core/types/platform.ts +3 -5
- package/src/core/utils/__tests__/deepClone.test.ts +317 -0
- package/src/core/utils/__tests__/index.test.ts +2 -1
- package/src/core/utils/chartInstances.ts +13 -0
- package/src/core/utils/common.ts +20 -29
- package/src/core/utils/deepClone.ts +114 -0
- package/src/core/utils/download.ts +128 -0
- package/src/core/utils/drillDown.ts +34 -353
- package/src/core/utils/drillDownHelpers.ts +426 -0
- package/src/core/utils/events.ts +12 -0
- package/src/core/utils/export/ExportUtils.ts +36 -67
- package/src/core/utils/format.ts +44 -0
- package/src/core/utils/index.ts +21 -154
- package/src/core/utils/merge.ts +25 -0
- package/src/core/utils/performance/PerformanceAnalyzer.ts +38 -21
- package/src/core/utils/performance/hooks.ts +7 -0
- package/src/core/utils/performance/index.ts +2 -0
- package/src/{hooks → core/utils/performance}/useAnimation.ts +45 -41
- package/src/core/utils/performance/useDataZoom.ts +324 -0
- package/src/{hooks → core/utils/performance}/usePerformance.ts +49 -41
- package/src/core/utils/performance/usePerformanceHooks.ts +278 -0
- package/src/core/utils/performanceUtils.ts +310 -0
- package/src/core/utils/runtime.ts +190 -0
- package/src/core/utils/setOptionUtils.ts +59 -0
- package/src/core/version.ts +14 -0
- package/src/editor/EnhancedThemeEditor.tsx +362 -540
- package/src/editor/ThemeEditor.tsx +55 -321
- package/src/editor/components/ThemeBasicSettings.tsx +113 -0
- package/src/editor/components/ThemeColorEditor.tsx +105 -0
- package/src/editor/components/ThemeSelector.tsx +70 -0
- package/src/editor/hooks/useThemeEditorState.ts +201 -0
- package/src/editor/index.ts +10 -2
- package/src/hooks/__tests__/index.test.tsx +3 -1
- package/src/hooks/chartConnectHelpers.ts +341 -0
- package/src/hooks/index.ts +55 -660
- package/src/hooks/types.ts +189 -0
- package/src/hooks/useChartAutoResize.ts +73 -0
- package/src/hooks/useChartConnect.ts +92 -238
- package/src/hooks/useChartDownload.ts +25 -27
- package/src/hooks/useChartHistory.ts +34 -49
- package/src/hooks/useChartInit.ts +59 -0
- package/src/hooks/useChartOptions.ts +259 -0
- package/src/hooks/useChartPerformance.ts +109 -0
- package/src/hooks/useChartSelection.ts +52 -49
- package/src/hooks/useChartTheme.ts +51 -0
- package/src/hooks/useDataTransform.ts +19 -4
- package/src/hooks/utils/chartDownloadUtils.ts +40 -53
- package/src/hooks/utils/dataTransformUtils.ts +22 -0
- package/src/index.ts +48 -34
- package/src/main.tsx +4 -9
- package/src/react-dom.d.ts +3 -3
- package/src/themes/index.ts +30 -855
- package/src/themes/palettes/blue-green.ts +13 -0
- package/src/themes/palettes/chalk.ts +13 -0
- package/src/themes/palettes/cyber.ts +44 -0
- package/src/themes/palettes/dark.ts +52 -0
- package/src/themes/palettes/default.ts +52 -0
- package/src/themes/palettes/elegant.ts +34 -0
- package/src/themes/palettes/forest.ts +13 -0
- package/src/themes/palettes/glass.ts +49 -0
- package/src/themes/palettes/golden.ts +13 -0
- package/src/themes/palettes/neon.ts +43 -0
- package/src/themes/palettes/ocean.ts +39 -0
- package/src/themes/palettes/pastel.ts +37 -0
- package/src/themes/palettes/purple-passion.ts +13 -0
- package/src/themes/palettes/retro.ts +33 -0
- package/src/themes/palettes/sunset.ts +40 -0
- package/src/themes/palettes/walden.ts +13 -0
- package/src/themes/registry.ts +184 -0
- package/src/themes/types.ts +213 -0
- package/src/charts/bar/__tests__/index.test.tsx +0 -113
- package/src/charts/bar/index.tsx +0 -14
- package/src/charts/candlestick/__tests__/index.test.tsx +0 -40
- package/src/charts/candlestick/index.tsx +0 -13
- package/src/charts/gauge/index.tsx +0 -14
- package/src/charts/line/__tests__/index.test.tsx +0 -107
- package/src/charts/line/index.tsx +0 -15
- package/src/charts/pie/__tests__/index.test.tsx +0 -112
- package/src/charts/pie/index.tsx +0 -14
- package/src/charts/scatter/index.tsx +0 -14
- package/src/charts/sunburst/index.tsx +0 -18
- package/src/charts/treemap/index.tsx +0 -18
- package/src/core/utils/codeGenerator/CodeGenerator.ts +0 -669
- package/src/core/utils/codeGenerator/index.ts +0 -13
- package/src/core/utils/codeGenerator/types.ts +0 -198
- package/src/core/utils/configGenerator/ConfigGenerator.ts +0 -583
- package/src/core/utils/configGenerator/index.ts +0 -13
- package/src/core/utils/configGenerator/types.ts +0 -445
- package/src/core/utils/debug/DebugPanel.tsx +0 -637
- package/src/core/utils/debug/debugger.ts +0 -322
- package/src/core/utils/debug/index.ts +0 -21
- package/src/core/utils/debug/types.ts +0 -142
- package/src/hooks/useDataZoom.ts +0 -323
|
@@ -1,8 +1,22 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1
2
|
/**
|
|
2
3
|
* DrillDown - 数据下钻工具
|
|
3
4
|
* 支持点击图表数据项时,自动下钻到更细粒度的数据视图
|
|
5
|
+
*
|
|
6
|
+
* @refactor 已拆分为多个辅助函数,详见 drillDownHelpers.ts
|
|
4
7
|
*/
|
|
5
|
-
import type { EChartsOption } from 'echarts';
|
|
8
|
+
import type { ECharts, EChartsOption, ECElementEvent } from 'echarts';
|
|
9
|
+
import {
|
|
10
|
+
buildOptionFromSources,
|
|
11
|
+
getDrillDownOption,
|
|
12
|
+
getCurrentLevelSources,
|
|
13
|
+
hasDrillDownData,
|
|
14
|
+
findMatchedSource,
|
|
15
|
+
executeDrillDown,
|
|
16
|
+
executeDrillUp,
|
|
17
|
+
executeReset,
|
|
18
|
+
executeDrillTo,
|
|
19
|
+
} from './drillDownHelpers';
|
|
6
20
|
|
|
7
21
|
// ============================================================================
|
|
8
22
|
// 类型定义
|
|
@@ -56,7 +70,7 @@ export interface DrillDownEventParams {
|
|
|
56
70
|
/** 点击的数据项名称 */
|
|
57
71
|
name: string | number;
|
|
58
72
|
/** 点击的数据项值 */
|
|
59
|
-
value:
|
|
73
|
+
value: unknown;
|
|
60
74
|
/** 下钻后的数据源 */
|
|
61
75
|
sources: DrillDownSource[];
|
|
62
76
|
/** 下钻后的图表配置 */
|
|
@@ -86,7 +100,7 @@ export interface DrillDownReturn {
|
|
|
86
100
|
* @param chartInstance ECharts 实例
|
|
87
101
|
* @param config 下钻配置
|
|
88
102
|
*/
|
|
89
|
-
init: (chartInstance:
|
|
103
|
+
init: (chartInstance: ECharts, config: DrillDownConfig) => void;
|
|
90
104
|
/**
|
|
91
105
|
* 返回上一层
|
|
92
106
|
*/
|
|
@@ -104,12 +118,12 @@ export interface DrillDownReturn {
|
|
|
104
118
|
* 绑定图表点击事件
|
|
105
119
|
* @param chartInstance ECharts 实例
|
|
106
120
|
*/
|
|
107
|
-
bindClick: (chartInstance:
|
|
121
|
+
bindClick: (chartInstance: ECharts) => void;
|
|
108
122
|
/**
|
|
109
123
|
* 解绑图表点击事件
|
|
110
124
|
* @param chartInstance ECharts 实例
|
|
111
125
|
*/
|
|
112
|
-
unbindClick: (chartInstance:
|
|
126
|
+
unbindClick: (chartInstance: ECharts) => void;
|
|
113
127
|
/**
|
|
114
128
|
* 手动触发下钻到指定层级
|
|
115
129
|
* @param level 目标层级
|
|
@@ -138,7 +152,7 @@ export interface DrillDownReturn {
|
|
|
138
152
|
|
|
139
153
|
interface DrillDownState {
|
|
140
154
|
/** 图表实例 */
|
|
141
|
-
chartInstance:
|
|
155
|
+
chartInstance: ECharts | null;
|
|
142
156
|
/** 当前配置 */
|
|
143
157
|
config: DrillDownConfig;
|
|
144
158
|
/** 当前层级 */
|
|
@@ -148,11 +162,11 @@ interface DrillDownState {
|
|
|
148
162
|
/** 当前图表 option */
|
|
149
163
|
currentOption: EChartsOption;
|
|
150
164
|
/** 初始 option(用于重置) */
|
|
151
|
-
initialOption:
|
|
165
|
+
initialOption: Record<string, unknown>;
|
|
152
166
|
/** 是否已初始化 */
|
|
153
167
|
initialized: boolean;
|
|
154
168
|
/** 事件处理器引用(用于解绑) */
|
|
155
|
-
clickHandler: ((params:
|
|
169
|
+
clickHandler: ((params: ECElementEvent) => void) | null;
|
|
156
170
|
}
|
|
157
171
|
|
|
158
172
|
// ============================================================================
|
|
@@ -204,178 +218,11 @@ export function createDrillDown(initialConfig?: Partial<DrillDownConfig>): Drill
|
|
|
204
218
|
clickHandler: null,
|
|
205
219
|
};
|
|
206
220
|
|
|
207
|
-
// ============================================================
|
|
208
|
-
// 内部方法
|
|
209
|
-
// ============================================================
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* 根据层级和触发数据项获取下钻后的图表配置
|
|
213
|
-
*/
|
|
214
|
-
const getDrillDownOption = (
|
|
215
|
-
level: number,
|
|
216
|
-
dataItem: DrillDownSource | undefined,
|
|
217
|
-
direction: 'down' | 'up' | 'reset'
|
|
218
|
-
): EChartsOption => {
|
|
219
|
-
const { config } = state;
|
|
220
|
-
let targetSources: DrillDownSource[] = [];
|
|
221
|
-
let targetOption: EChartsOption = {};
|
|
222
|
-
|
|
223
|
-
if (direction === 'reset' || level === 0) {
|
|
224
|
-
// 重置或回到第一层:使用初始数据
|
|
225
|
-
if (config.initialSources) {
|
|
226
|
-
targetSources = config.initialSources;
|
|
227
|
-
// 从 initialSources 构建图表 option
|
|
228
|
-
targetOption = buildOptionFromSources(targetSources);
|
|
229
|
-
} else {
|
|
230
|
-
// 如果没有 initialSources,返回空 option,让用户重新 setOption
|
|
231
|
-
targetOption = {};
|
|
232
|
-
}
|
|
233
|
-
} else if (direction === 'up') {
|
|
234
|
-
// 上钻:从 history 中找到上一层的状态
|
|
235
|
-
const prevHistory = state.history[level - 1];
|
|
236
|
-
if (prevHistory && prevHistory.dataItem.chartOption) {
|
|
237
|
-
targetOption = prevHistory.dataItem.chartOption;
|
|
238
|
-
} else {
|
|
239
|
-
// 尝试从 children 构建
|
|
240
|
-
targetSources = prevHistory?.dataItem.children ?? [];
|
|
241
|
-
targetOption = buildOptionFromSources(targetSources);
|
|
242
|
-
}
|
|
243
|
-
} else if (direction === 'down' && dataItem) {
|
|
244
|
-
// 下钻
|
|
245
|
-
if (dataItem.chartOption) {
|
|
246
|
-
// 优先使用自定义 chartOption
|
|
247
|
-
targetOption = dataItem.chartOption;
|
|
248
|
-
} else if (dataItem.children && dataItem.children.length > 0) {
|
|
249
|
-
// 从 children 构建图表 option
|
|
250
|
-
targetSources = dataItem.children;
|
|
251
|
-
targetOption = buildOptionFromSources(targetSources);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return targetOption;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* 从 DrillDownSource 数组构建 ECharts option
|
|
260
|
-
*/
|
|
261
|
-
const buildOptionFromSources = (sources: DrillDownSource[]): EChartsOption => {
|
|
262
|
-
if (!sources || sources.length === 0) return {};
|
|
263
|
-
|
|
264
|
-
const names = sources.map((s) => s.name);
|
|
265
|
-
const values = sources.map((s) => s.value);
|
|
266
|
-
|
|
267
|
-
return {
|
|
268
|
-
xAxis: {
|
|
269
|
-
type: 'category',
|
|
270
|
-
data: names,
|
|
271
|
-
},
|
|
272
|
-
yAxis: {
|
|
273
|
-
type: 'value',
|
|
274
|
-
},
|
|
275
|
-
series: [
|
|
276
|
-
{
|
|
277
|
-
type: 'bar',
|
|
278
|
-
data: values,
|
|
279
|
-
},
|
|
280
|
-
],
|
|
281
|
-
};
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* 检查是否有下钻数据
|
|
286
|
-
*/
|
|
287
|
-
const hasDrillDownData = (dataItem: DrillDownSource | undefined): boolean => {
|
|
288
|
-
if (!dataItem) return false;
|
|
289
|
-
return !!(dataItem.children && dataItem.children.length > 0) || !!dataItem.chartOption;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* 执行下钻
|
|
294
|
-
*/
|
|
295
|
-
const executeDrillDown = (params: any) => {
|
|
296
|
-
const { config, chartInstance } = state;
|
|
297
|
-
if (!chartInstance) return;
|
|
298
|
-
|
|
299
|
-
const { name, value } = params;
|
|
300
|
-
|
|
301
|
-
// 在当前层级的数据中查找匹配项
|
|
302
|
-
let matchedSource: DrillDownSource | undefined;
|
|
303
|
-
|
|
304
|
-
// 尝试从 history 中获取当前层级的数据源
|
|
305
|
-
const currentLevelSources = getCurrentLevelSources();
|
|
306
|
-
matchedSource = currentLevelSources.find(
|
|
307
|
-
(s) => String(s.name) === String(name) || s.value === value
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
// 如果没找到,尝试在 initialSources 中查找
|
|
311
|
-
if (!matchedSource && state.currentLevel === 0 && config.initialSources) {
|
|
312
|
-
matchedSource = config.initialSources.find(
|
|
313
|
-
(s) => String(s.name) === String(name) || s.value === value
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// 如果是最后一级(不能再下钻)或者找不到匹配项,不执行下钻
|
|
318
|
-
if (!hasDrillDownData(matchedSource)) {
|
|
319
|
-
console.warn('[DrillDown] No drill-down data available for:', name);
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// 记录历史
|
|
324
|
-
if (matchedSource) {
|
|
325
|
-
state.history.push({ level: state.currentLevel, dataItem: matchedSource });
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// 更新层级
|
|
329
|
-
state.currentLevel += 1;
|
|
330
|
-
|
|
331
|
-
// 获取新的图表配置
|
|
332
|
-
const newOption = getDrillDownOption(state.currentLevel, matchedSource, 'down');
|
|
333
|
-
|
|
334
|
-
// 更新图表
|
|
335
|
-
if (newOption && Object.keys(newOption).length > 0) {
|
|
336
|
-
chartInstance.setOption(newOption, true);
|
|
337
|
-
state.currentOption = newOption;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// 触发回调
|
|
341
|
-
config.onDrillDown?.({
|
|
342
|
-
level: state.currentLevel,
|
|
343
|
-
name: matchedSource?.name ?? name,
|
|
344
|
-
value: matchedSource?.value ?? value,
|
|
345
|
-
sources: matchedSource?.children ?? [],
|
|
346
|
-
chartOption: newOption,
|
|
347
|
-
rawParams: params,
|
|
348
|
-
});
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* 获取当前层级的数据源列表
|
|
353
|
-
*/
|
|
354
|
-
const getCurrentLevelSources = (): DrillDownSource[] => {
|
|
355
|
-
const { config } = state;
|
|
356
|
-
|
|
357
|
-
if (state.currentLevel === 0) {
|
|
358
|
-
// 第 0 层:使用 initialSources 或从 dimension 匹配
|
|
359
|
-
if (config.initialSources) {
|
|
360
|
-
return config.initialSources;
|
|
361
|
-
}
|
|
362
|
-
return [];
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// 其他层级:从 history 中找到上一层点击的数据项的 children
|
|
366
|
-
const lastHistory = state.history[state.history.length - 1];
|
|
367
|
-
if (lastHistory && lastHistory.dataItem.children) {
|
|
368
|
-
return lastHistory.dataItem.children;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
return [];
|
|
372
|
-
};
|
|
373
|
-
|
|
374
221
|
// ============================================================
|
|
375
222
|
// 实例方法
|
|
376
223
|
// ============================================================
|
|
377
224
|
|
|
378
|
-
const init = (chartInstance:
|
|
225
|
+
const init = (chartInstance: ECharts, config: DrillDownConfig): void => {
|
|
379
226
|
if (!chartInstance) {
|
|
380
227
|
console.error('[DrillDown] Invalid chart instance');
|
|
381
228
|
return;
|
|
@@ -400,69 +247,16 @@ export function createDrillDown(initialConfig?: Partial<DrillDownConfig>): Drill
|
|
|
400
247
|
};
|
|
401
248
|
|
|
402
249
|
const drillUp = (): void => {
|
|
403
|
-
|
|
404
|
-
if (!chartInstance || state.currentLevel <= 0) {
|
|
405
|
-
console.warn('[DrillDown] Cannot drill up: already at top level');
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
const previousLevel = state.currentLevel;
|
|
410
|
-
|
|
411
|
-
// 弹出历史
|
|
412
|
-
state.history.pop();
|
|
413
|
-
|
|
414
|
-
// 更新层级
|
|
415
|
-
state.currentLevel -= 1;
|
|
416
|
-
|
|
417
|
-
// 获取新的图表配置
|
|
418
|
-
const newOption = getDrillDownOption(state.currentLevel, undefined, 'up');
|
|
419
|
-
|
|
420
|
-
// 更新图表
|
|
421
|
-
if (newOption && Object.keys(newOption).length > 0) {
|
|
422
|
-
chartInstance.setOption(newOption, true);
|
|
423
|
-
state.currentOption = newOption;
|
|
424
|
-
} else if (state.currentLevel === 0 && state.initialOption) {
|
|
425
|
-
chartInstance.setOption(state.initialOption, true);
|
|
426
|
-
state.currentOption = state.initialOption;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// 触发回调
|
|
430
|
-
config.onDrillUp?.({
|
|
431
|
-
previousLevel,
|
|
432
|
-
currentLevel: state.currentLevel,
|
|
433
|
-
chartOption: newOption,
|
|
434
|
-
});
|
|
250
|
+
executeDrillUp(state, state.config);
|
|
435
251
|
};
|
|
436
252
|
|
|
437
253
|
const reset = (): void => {
|
|
438
|
-
|
|
439
|
-
if (!chartInstance) return;
|
|
440
|
-
|
|
441
|
-
const previousLevel = state.currentLevel;
|
|
442
|
-
|
|
443
|
-
// 清空历史
|
|
444
|
-
state.history = [];
|
|
445
|
-
state.currentLevel = 0;
|
|
446
|
-
|
|
447
|
-
// 获取初始配置
|
|
448
|
-
const newOption = getDrillDownOption(0, undefined, 'reset');
|
|
449
|
-
|
|
450
|
-
// 更新图表
|
|
451
|
-
if (newOption && Object.keys(newOption).length > 0) {
|
|
452
|
-
chartInstance.setOption(newOption, true);
|
|
453
|
-
state.currentOption = newOption;
|
|
454
|
-
} else if (state.initialOption && Object.keys(state.initialOption).length > 0) {
|
|
455
|
-
chartInstance.setOption(state.initialOption, true);
|
|
456
|
-
state.currentOption = state.initialOption;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// 触发回调
|
|
460
|
-
config.onReset?.({ level: 0 });
|
|
254
|
+
executeReset(state, state.config);
|
|
461
255
|
};
|
|
462
256
|
|
|
463
257
|
const getCurrentLevel = (): number => state.currentLevel;
|
|
464
258
|
|
|
465
|
-
const bindClick = (chartInstance:
|
|
259
|
+
const bindClick = (chartInstance: ECharts): void => {
|
|
466
260
|
const instance = chartInstance || state.chartInstance;
|
|
467
261
|
if (!instance) {
|
|
468
262
|
console.error('[DrillDown] No chart instance to bind');
|
|
@@ -475,14 +269,14 @@ export function createDrillDown(initialConfig?: Partial<DrillDownConfig>): Drill
|
|
|
475
269
|
}
|
|
476
270
|
|
|
477
271
|
// 创建新的点击处理器
|
|
478
|
-
state.clickHandler = (params:
|
|
479
|
-
executeDrillDown(params);
|
|
272
|
+
state.clickHandler = (params: ECElementEvent) => {
|
|
273
|
+
executeDrillDown(params, state);
|
|
480
274
|
};
|
|
481
275
|
|
|
482
276
|
instance.on('click', state.clickHandler);
|
|
483
277
|
};
|
|
484
278
|
|
|
485
|
-
const unbindClick = (chartInstance:
|
|
279
|
+
const unbindClick = (chartInstance: ECharts): void => {
|
|
486
280
|
const instance = chartInstance || state.chartInstance;
|
|
487
281
|
if (!instance || !state.clickHandler) return;
|
|
488
282
|
|
|
@@ -491,80 +285,26 @@ export function createDrillDown(initialConfig?: Partial<DrillDownConfig>): Drill
|
|
|
491
285
|
};
|
|
492
286
|
|
|
493
287
|
const drillTo = (level: number, dataItem?: DrillDownSource): void => {
|
|
494
|
-
|
|
495
|
-
if (!chartInstance) return;
|
|
496
|
-
|
|
497
|
-
if (level < 0 || level > state.history.length) {
|
|
498
|
-
console.warn('[DrillDown] Invalid drill level:', level);
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
const previousLevel = state.currentLevel;
|
|
503
|
-
state.currentLevel = level;
|
|
504
|
-
|
|
505
|
-
if (level === state.history.length) {
|
|
506
|
-
// 下钻
|
|
507
|
-
if (dataItem) {
|
|
508
|
-
state.history.push({ level: level - 1, dataItem });
|
|
509
|
-
}
|
|
510
|
-
} else if (level < state.history.length) {
|
|
511
|
-
// 上钻或跳转:调整 history
|
|
512
|
-
state.history = state.history.slice(0, level);
|
|
513
|
-
} else {
|
|
514
|
-
// level === 0, reset
|
|
515
|
-
state.history = [];
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
const newOption = getDrillDownOption(level, dataItem, level === 0 ? 'reset' : 'down');
|
|
519
|
-
|
|
520
|
-
if (newOption && Object.keys(newOption).length > 0) {
|
|
521
|
-
chartInstance.setOption(newOption, true);
|
|
522
|
-
state.currentOption = newOption;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
if (level > previousLevel) {
|
|
526
|
-
config.onDrillDown?.({
|
|
527
|
-
level,
|
|
528
|
-
name: dataItem?.name ?? '',
|
|
529
|
-
value: dataItem?.value ?? 0,
|
|
530
|
-
sources: dataItem?.children ?? [],
|
|
531
|
-
chartOption: newOption,
|
|
532
|
-
rawParams: {},
|
|
533
|
-
});
|
|
534
|
-
} else if (level < previousLevel) {
|
|
535
|
-
config.onDrillUp?.({
|
|
536
|
-
previousLevel,
|
|
537
|
-
currentLevel: level,
|
|
538
|
-
chartOption: newOption,
|
|
539
|
-
});
|
|
540
|
-
} else {
|
|
541
|
-
config.onReset?.({ level: 0 });
|
|
542
|
-
}
|
|
288
|
+
executeDrillTo(level, dataItem, state, state.config);
|
|
543
289
|
};
|
|
544
290
|
|
|
545
291
|
const getHistory = (): Array<{ level: number; dataItem: DrillDownSource }> => {
|
|
546
292
|
return [...state.history];
|
|
547
293
|
};
|
|
548
294
|
|
|
549
|
-
const canDrillUp = (): boolean =>
|
|
550
|
-
return state.currentLevel > 0;
|
|
551
|
-
};
|
|
295
|
+
const canDrillUp = (): boolean => state.currentLevel > 0;
|
|
552
296
|
|
|
553
297
|
const dispose = (): void => {
|
|
554
298
|
if (state.chartInstance && state.clickHandler) {
|
|
555
|
-
|
|
299
|
+
state.chartInstance.off('click', state.clickHandler);
|
|
556
300
|
}
|
|
557
301
|
state.chartInstance = null;
|
|
558
|
-
state.
|
|
302
|
+
state.clickHandler = null;
|
|
559
303
|
state.history = [];
|
|
560
304
|
state.currentLevel = 0;
|
|
561
305
|
state.initialized = false;
|
|
562
306
|
};
|
|
563
307
|
|
|
564
|
-
// ============================================================
|
|
565
|
-
// 返回公开接口
|
|
566
|
-
// ============================================================
|
|
567
|
-
|
|
568
308
|
return {
|
|
569
309
|
init,
|
|
570
310
|
drillUp,
|
|
@@ -580,64 +320,5 @@ export function createDrillDown(initialConfig?: Partial<DrillDownConfig>): Drill
|
|
|
580
320
|
}
|
|
581
321
|
|
|
582
322
|
// ============================================================================
|
|
583
|
-
//
|
|
323
|
+
// 导出
|
|
584
324
|
// ============================================================================
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* 判断 DrillDownSource 是否有下钻能力
|
|
588
|
-
*/
|
|
589
|
-
export function canDrillDown(source: DrillDownSource): boolean {
|
|
590
|
-
return !!(source.children && source.children.length > 0) || !!source.chartOption;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
/**
|
|
594
|
-
* 从扁平数据构建层级结构(辅助函数)
|
|
595
|
-
*/
|
|
596
|
-
export function buildHierarchy(
|
|
597
|
-
data: Array<{ [key: string]: unknown }>,
|
|
598
|
-
dimensionKey: string,
|
|
599
|
-
valueKey: string,
|
|
600
|
-
childrenKey: string = 'children'
|
|
601
|
-
): DrillDownSource[] {
|
|
602
|
-
const sourceMap: Record<string, DrillDownSource[]> = {};
|
|
603
|
-
|
|
604
|
-
data.forEach((item) => {
|
|
605
|
-
const dimValue = String(item[dimensionKey]);
|
|
606
|
-
if (!sourceMap[dimValue]) {
|
|
607
|
-
sourceMap[dimValue] = [];
|
|
608
|
-
}
|
|
609
|
-
sourceMap[dimValue].push({
|
|
610
|
-
name: item[dimensionKey] as string | number,
|
|
611
|
-
value: item[valueKey] as string | number,
|
|
612
|
-
children: item[childrenKey]
|
|
613
|
-
? buildHierarchy(item[childrenKey] as Array<{ [key: string]: unknown }>, dimensionKey, valueKey, childrenKey)
|
|
614
|
-
: undefined,
|
|
615
|
-
});
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
return Object.values(sourceMap).flat();
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
/**
|
|
622
|
-
* 创建典型的地区下钻示例配置
|
|
623
|
-
*/
|
|
624
|
-
export function createRegionDrillDown(
|
|
625
|
-
regionData: Record<string, DrillDownSource[]>
|
|
626
|
-
): DrillDownConfig {
|
|
627
|
-
return {
|
|
628
|
-
dimension: 'region',
|
|
629
|
-
sources: regionData,
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
* 创建典型的分类下钻示例配置
|
|
635
|
-
*/
|
|
636
|
-
export function createCategoryDrillDown(
|
|
637
|
-
categoryData: Record<string, DrillDownSource[]>
|
|
638
|
-
): DrillDownConfig {
|
|
639
|
-
return {
|
|
640
|
-
dimension: 'category',
|
|
641
|
-
sources: categoryData,
|
|
642
|
-
};
|
|
643
|
-
}
|