@fses/workbench-app 0.2.0 → 0.2.1
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/WORKBENCH-CLOSURE.json +80 -0
- package/node_modules/@byteluck/agentic-protocol/LICENSE +9 -0
- package/node_modules/@byteluck/agentic-protocol/README.md +74 -0
- package/node_modules/@byteluck/agentic-protocol/dist/index.d.ts +1623 -0
- package/node_modules/@byteluck/agentic-protocol/dist/index.mjs +3380 -0
- package/node_modules/@byteluck/agentic-protocol/package.json +37 -0
- package/node_modules/@byteluck/workbench-skill-contracts/LICENSE +9 -0
- package/node_modules/@byteluck/workbench-skill-contracts/dist/index.d.ts +234 -0
- package/node_modules/@byteluck/workbench-skill-contracts/dist/index.mjs +394 -0
- package/node_modules/@byteluck/workbench-skill-contracts/package.json +37 -0
- package/node_modules/@fses/ai-chat/LICENSE +9 -0
- package/node_modules/@fses/ai-chat/README.md +320 -0
- package/node_modules/@fses/ai-chat/dist/chart-card/data.d.ts +12 -0
- package/node_modules/@fses/ai-chat/dist/chart-card/from-markdown.d.ts +11 -0
- package/node_modules/@fses/ai-chat/dist/chart-card/from-tool.d.ts +8 -0
- package/node_modules/@fses/ai-chat/dist/chart-card/options.d.ts +4 -0
- package/node_modules/@fses/ai-chat/dist/chart-card/trace.d.ts +19 -0
- package/node_modules/@fses/ai-chat/dist/chart-card/types.d.ts +133 -0
- package/node_modules/@fses/ai-chat/dist/components/CardRecommendationDeferredDraft.vue.d.ts +13 -0
- package/node_modules/@fses/ai-chat/dist/components/CardRecommendationDraft.vue.d.ts +18 -0
- package/node_modules/@fses/ai-chat/dist/components/ChartCardRenderer.vue.d.ts +11 -0
- package/node_modules/@fses/ai-chat/dist/components/ChatMessageItem.vue.d.ts +76 -0
- package/node_modules/@fses/ai-chat/dist/components/ChatMessageList.vue.d.ts +79 -0
- package/node_modules/@fses/ai-chat/dist/components/ChatSender.vue.d.ts +98 -0
- package/node_modules/@fses/ai-chat/dist/components/CollapsedToolActivity.vue.d.ts +9 -0
- package/node_modules/@fses/ai-chat/dist/components/ContextUsageRing.vue.d.ts +12 -0
- package/node_modules/@fses/ai-chat/dist/components/EChartsView.vue.d.ts +6 -0
- package/node_modules/@fses/ai-chat/dist/components/FsesAiChat.vue.d.ts +306 -0
- package/node_modules/@fses/ai-chat/dist/components/PlanDraftCard.vue.d.ts +19 -0
- package/node_modules/@fses/ai-chat/dist/components/ShellExecPanel.vue.d.ts +6 -0
- package/node_modules/@fses/ai-chat/dist/components/TaskTodoPlanBar.vue.d.ts +6 -0
- package/node_modules/@fses/ai-chat/dist/components/ThinkingShimmer.vue.d.ts +6 -0
- package/node_modules/@fses/ai-chat/dist/composables/context-usage.d.ts +11 -0
- package/node_modules/@fses/ai-chat/dist/composables/types.d.ts +465 -0
- package/node_modules/@fses/ai-chat/dist/composables/useChat.d.ts +2 -0
- package/node_modules/@fses/ai-chat/dist/composables/useSystemEChartsIcon.d.ts +11 -0
- package/node_modules/@fses/ai-chat/dist/fses-ai-chat.js +11408 -0
- package/node_modules/@fses/ai-chat/dist/fses-ai-chat.umd.cjs +25 -0
- package/node_modules/@fses/ai-chat/dist/index.d.ts +17 -0
- package/node_modules/@fses/ai-chat/dist/plugin.d.ts +8 -0
- package/node_modules/@fses/ai-chat/dist/style.css +1 -0
- package/node_modules/@fses/ai-chat/dist/utils/assistant-markdown.d.ts +11 -0
- package/node_modules/@fses/ai-chat/dist/utils/attachment-upload.d.ts +22 -0
- package/node_modules/@fses/ai-chat/dist/utils/card-recommendation-config-summary.d.ts +86 -0
- package/node_modules/@fses/ai-chat/dist/utils/card-recommendation-field-label.d.ts +24 -0
- package/node_modules/@fses/ai-chat/dist/utils/card-recommendation-source.d.ts +18 -0
- package/node_modules/@fses/ai-chat/dist/utils/card-recommendation-title-source.d.ts +12 -0
- package/node_modules/@fses/ai-chat/dist/utils/chart-card-visibility.d.ts +24 -0
- package/node_modules/@fses/ai-chat/dist/utils/derived-process-labels.d.ts +13 -0
- package/node_modules/@fses/ai-chat/dist/utils/echarts-recommendation-icon.d.ts +36 -0
- package/node_modules/@fses/ai-chat/dist/utils/group-messages.d.ts +30 -0
- package/node_modules/@fses/ai-chat/dist/utils/status-activity.d.ts +48 -0
- package/node_modules/@fses/ai-chat/dist/utils/system-echarts-template-icons.generated.d.ts +305 -0
- package/node_modules/@fses/ai-chat/dist/utils/system-echarts-template.d.ts +20 -0
- package/node_modules/@fses/ai-chat/dist/utils/task-todo-plan.d.ts +40 -0
- package/node_modules/@fses/ai-chat/dist/utils/workbench-echarts-theme.d.ts +35 -0
- package/node_modules/@fses/ai-chat/package.json +81 -0
- package/node_modules/@fses/workbench-card/LICENSE +9 -0
- package/node_modules/@fses/workbench-card/README.md +81 -0
- package/node_modules/@fses/workbench-card/dist/chart/index.d.ts +8 -0
- package/node_modules/@fses/workbench-card/dist/fses-workbench-card-echarts-protocol.js +2230 -0
- package/node_modules/@fses/workbench-card/dist/fses-workbench-card-renderers.js +33731 -0
- package/node_modules/@fses/workbench-card/dist/fses-workbench-card.js +21238 -0
- package/node_modules/@fses/workbench-card/dist/fses-workbench-card.umd.cjs +1 -0
- package/node_modules/@fses/workbench-card/dist/index.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/registry/cardRegistry.d.ts +50 -0
- package/node_modules/@fses/workbench-card/dist/registry/compositeCardPatterns.d.ts +39 -0
- package/node_modules/@fses/workbench-card/dist/registry/echartsTemplateCategories.d.ts +20 -0
- package/node_modules/@fses/workbench-card/dist/registry/echartsTemplateRegistry.d.ts +1158 -0
- package/node_modules/@fses/workbench-card/dist/registry/echartsTemplateRegistry.generated.d.ts +1141 -0
- package/node_modules/@fses/workbench-card/dist/registry/echartsTemplateTypes.d.ts +76 -0
- package/node_modules/@fses/workbench-card/dist/registry/index.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/WorkbenchBlockRenderer.vue.d.ts +55 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/ChartRegistry.vue.d.ts +22 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/EChartsProtocolRenderer.vue.d.ts +34 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/chartRendererRegistry.d.ts +219 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/chartResponsiveLayout.d.ts +47 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/dynamicEchartOption.d.ts +30 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/adapter.d.ts +73 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/composite.converter.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/configOnly.converter.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/geo.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/graphic.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/layout.converter.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/network.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/scene3D.converter.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/series.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/table.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/timeline.converter.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/transition.converter.d.ts +11 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/tree.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/converters/tuple.converter.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/index.d.ts +9 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/merger.d.ts +16 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echarts-protocol/types.d.ts +447 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echartsRuntimeInteractions.d.ts +30 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echartsTitle.d.ts +13 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/echartsTooltipPortal.d.ts +12 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/types.d.ts +47 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/useEchart.d.ts +29 -0
- package/node_modules/@fses/workbench-card/dist/renderers/chart/workbenchChartTheme.d.ts +36 -0
- package/node_modules/@fses/workbench-card/dist/renderers/custom-canvas/canvasLayoutBindings.d.ts +86 -0
- package/node_modules/@fses/workbench-card/dist/renderers/hostBridge.d.ts +61 -0
- package/node_modules/@fses/workbench-card/dist/renderers/index.d.ts +17 -0
- package/node_modules/@fses/workbench-card/dist/renderers/native/nativeBindings.d.ts +145 -0
- package/node_modules/@fses/workbench-card/dist/renderers/nested/nestedBlockBindings.d.ts +107 -0
- package/node_modules/@fses/workbench-card/dist/renderers/quickLinkDisplay.d.ts +24 -0
- package/node_modules/@fses/workbench-card/dist/renderers/reference-composite/referenceCompositeBindings.d.ts +171 -0
- package/node_modules/@fses/workbench-card/dist/renderers/reference-composite/referenceRiskAndStrategyBindings.d.ts +91 -0
- package/node_modules/@fses/workbench-card/dist/renderers/resizableTable.d.ts +51 -0
- package/node_modules/@fses/workbench-card/dist/renderers/style.css +1 -0
- package/node_modules/@fses/workbench-card/dist/renderers/tableDisplay.d.ts +25 -0
- package/node_modules/@fses/workbench-card/dist/renderers/useWorkbenchBlockRendererBindings.d.ts +580 -0
- package/node_modules/@fses/workbench-card/dist/shell/workbenchVisualShell.d.ts +48 -0
- package/node_modules/@fses/workbench-card/dist/style.css +1 -0
- package/node_modules/@fses/workbench-card/dist/types/block.d.ts +2002 -0
- package/node_modules/@fses/workbench-card/dist/types/canvas.d.ts +25 -0
- package/node_modules/@fses/workbench-card/dist/types/echartsProtocol.d.ts +445 -0
- package/node_modules/@fses/workbench-card/dist/types/index.d.ts +10 -0
- package/node_modules/@fses/workbench-card/dist/types/registry.d.ts +7 -0
- package/node_modules/@fses/workbench-card/dist/types/runtime.d.ts +34 -0
- package/node_modules/@fses/workbench-card/package.json +82 -0
- package/node_modules/@fses/workbench-card/src/chart/index.ts +8 -0
- package/node_modules/@fses/workbench-card/src/index.ts +13 -0
- package/node_modules/@fses/workbench-card/src/registry/cardRegistry.ts +476 -0
- package/node_modules/@fses/workbench-card/src/registry/compositeCardPatterns.ts +206 -0
- package/node_modules/@fses/workbench-card/src/registry/echartsTemplateCategories.ts +74 -0
- package/node_modules/@fses/workbench-card/src/registry/echartsTemplateRegistry.generated.ts +19951 -0
- package/node_modules/@fses/workbench-card/src/registry/echartsTemplateRegistry.ts +32 -0
- package/node_modules/@fses/workbench-card/src/registry/echartsTemplateTypes.ts +83 -0
- package/node_modules/@fses/workbench-card/src/registry/index.ts +10 -0
- package/node_modules/@fses/workbench-card/src/renderers/WorkbenchBlockRenderer.vue +2728 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/ChartRegistry.vue +221 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/EChartsProtocolRenderer.vue +304 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/chartRendererRegistry.ts +311 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/chartResponsiveLayout.ts +172 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/dynamicEchartOption.ts +127 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/adapter.ts +1349 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/composite.converter.ts +71 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/configOnly.converter.ts +45 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/geo.converter.ts +97 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/graphic.converter.ts +59 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/layout.converter.ts +53 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/network.converter.ts +82 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/scene3D.converter.ts +73 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/series.converter.ts +795 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/table.converter.ts +195 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/timeline.converter.ts +62 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/transition.converter.ts +58 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/tree.converter.ts +75 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/converters/tuple.converter.ts +112 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/index.ts +10 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/merger.ts +109 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echarts-protocol/types.ts +515 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echartsRuntimeInteractions.ts +450 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echartsTitle.ts +94 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/echartsTooltipPortal.ts +140 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/types.ts +53 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/useEchart.ts +1820 -0
- package/node_modules/@fses/workbench-card/src/renderers/chart/workbenchChartTheme.ts +240 -0
- package/node_modules/@fses/workbench-card/src/renderers/custom-canvas/canvasLayoutBindings.ts +660 -0
- package/node_modules/@fses/workbench-card/src/renderers/hostBridge.ts +74 -0
- package/node_modules/@fses/workbench-card/src/renderers/index.ts +25 -0
- package/node_modules/@fses/workbench-card/src/renderers/native/nativeBindings.ts +1081 -0
- package/node_modules/@fses/workbench-card/src/renderers/nested/nestedBlockBindings.ts +1349 -0
- package/node_modules/@fses/workbench-card/src/renderers/quickLinkDisplay.ts +53 -0
- package/node_modules/@fses/workbench-card/src/renderers/reference-composite/referenceCompositeBindings.ts +3205 -0
- package/node_modules/@fses/workbench-card/src/renderers/reference-composite/referenceRiskAndStrategyBindings.ts +1004 -0
- package/node_modules/@fses/workbench-card/src/renderers/resizableTable.ts +136 -0
- package/node_modules/@fses/workbench-card/src/renderers/tableDisplay.ts +140 -0
- package/node_modules/@fses/workbench-card/src/renderers/useWorkbenchBlockRendererBindings.ts +3192 -0
- package/node_modules/@fses/workbench-card/src/shell/workbenchVisualShell.ts +228 -0
- package/node_modules/@fses/workbench-card/src/styles/workbench-card.css +343 -0
- package/node_modules/@fses/workbench-card/src/types/block.ts +2487 -0
- package/node_modules/@fses/workbench-card/src/types/canvas.ts +30 -0
- package/node_modules/@fses/workbench-card/src/types/echartsProtocol.ts +513 -0
- package/node_modules/@fses/workbench-card/src/types/index.ts +10 -0
- package/node_modules/@fses/workbench-card/src/types/registry.ts +17 -0
- package/node_modules/@fses/workbench-card/src/types/runtime.ts +31 -0
- package/node_modules/dompurify/LICENSE +568 -0
- package/node_modules/dompurify/README.md +523 -0
- package/node_modules/dompurify/dist/purify.cjs.d.ts +451 -0
- package/node_modules/dompurify/dist/purify.cjs.js +1472 -0
- package/node_modules/dompurify/dist/purify.cjs.js.map +1 -0
- package/node_modules/dompurify/dist/purify.es.d.mts +448 -0
- package/node_modules/dompurify/dist/purify.es.mjs +1470 -0
- package/node_modules/dompurify/dist/purify.es.mjs.map +1 -0
- package/node_modules/dompurify/dist/purify.js +1478 -0
- package/node_modules/dompurify/dist/purify.js.map +1 -0
- package/node_modules/dompurify/dist/purify.min.js +3 -0
- package/node_modules/dompurify/dist/purify.min.js.map +1 -0
- package/node_modules/dompurify/package.json +168 -0
- package/node_modules/zod/LICENSE +21 -0
- package/node_modules/zod/README.md +208 -0
- package/node_modules/zod/index.cjs +33 -0
- package/node_modules/zod/index.d.cts +4 -0
- package/node_modules/zod/index.d.ts +4 -0
- package/node_modules/zod/index.js +4 -0
- package/node_modules/zod/package.json +118 -0
- package/node_modules/zod/src/index.ts +4 -0
- package/node_modules/zod/src/v3/ZodError.ts +330 -0
- package/node_modules/zod/src/v3/benchmarks/datetime.ts +58 -0
- package/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts +80 -0
- package/node_modules/zod/src/v3/benchmarks/index.ts +59 -0
- package/node_modules/zod/src/v3/benchmarks/ipv4.ts +57 -0
- package/node_modules/zod/src/v3/benchmarks/object.ts +69 -0
- package/node_modules/zod/src/v3/benchmarks/primitives.ts +162 -0
- package/node_modules/zod/src/v3/benchmarks/realworld.ts +63 -0
- package/node_modules/zod/src/v3/benchmarks/string.ts +55 -0
- package/node_modules/zod/src/v3/benchmarks/union.ts +80 -0
- package/node_modules/zod/src/v3/errors.ts +13 -0
- package/node_modules/zod/src/v3/external.ts +6 -0
- package/node_modules/zod/src/v3/helpers/enumUtil.ts +17 -0
- package/node_modules/zod/src/v3/helpers/errorUtil.ts +8 -0
- package/node_modules/zod/src/v3/helpers/parseUtil.ts +176 -0
- package/node_modules/zod/src/v3/helpers/partialUtil.ts +34 -0
- package/node_modules/zod/src/v3/helpers/typeAliases.ts +2 -0
- package/node_modules/zod/src/v3/helpers/util.ts +224 -0
- package/node_modules/zod/src/v3/index.ts +4 -0
- package/node_modules/zod/src/v3/locales/en.ts +124 -0
- package/node_modules/zod/src/v3/standard-schema.ts +113 -0
- package/node_modules/zod/src/v3/tests/Mocker.ts +54 -0
- package/node_modules/zod/src/v3/tests/all-errors.test.ts +157 -0
- package/node_modules/zod/src/v3/tests/anyunknown.test.ts +28 -0
- package/node_modules/zod/src/v3/tests/array.test.ts +71 -0
- package/node_modules/zod/src/v3/tests/async-parsing.test.ts +388 -0
- package/node_modules/zod/src/v3/tests/async-refinements.test.ts +46 -0
- package/node_modules/zod/src/v3/tests/base.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/bigint.test.ts +55 -0
- package/node_modules/zod/src/v3/tests/branded.test.ts +53 -0
- package/node_modules/zod/src/v3/tests/catch.test.ts +220 -0
- package/node_modules/zod/src/v3/tests/coerce.test.ts +133 -0
- package/node_modules/zod/src/v3/tests/complex.test.ts +56 -0
- package/node_modules/zod/src/v3/tests/custom.test.ts +31 -0
- package/node_modules/zod/src/v3/tests/date.test.ts +32 -0
- package/node_modules/zod/src/v3/tests/deepmasking.test.ts +186 -0
- package/node_modules/zod/src/v3/tests/default.test.ts +112 -0
- package/node_modules/zod/src/v3/tests/description.test.ts +33 -0
- package/node_modules/zod/src/v3/tests/discriminated-unions.test.ts +315 -0
- package/node_modules/zod/src/v3/tests/enum.test.ts +80 -0
- package/node_modules/zod/src/v3/tests/error.test.ts +551 -0
- package/node_modules/zod/src/v3/tests/firstparty.test.ts +87 -0
- package/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts +21 -0
- package/node_modules/zod/src/v3/tests/function.test.ts +257 -0
- package/node_modules/zod/src/v3/tests/generics.test.ts +48 -0
- package/node_modules/zod/src/v3/tests/instanceof.test.ts +37 -0
- package/node_modules/zod/src/v3/tests/intersection.test.ts +110 -0
- package/node_modules/zod/src/v3/tests/language-server.source.ts +76 -0
- package/node_modules/zod/src/v3/tests/language-server.test.ts +207 -0
- package/node_modules/zod/src/v3/tests/literal.test.ts +36 -0
- package/node_modules/zod/src/v3/tests/map.test.ts +110 -0
- package/node_modules/zod/src/v3/tests/masking.test.ts +4 -0
- package/node_modules/zod/src/v3/tests/mocker.test.ts +19 -0
- package/node_modules/zod/src/v3/tests/nan.test.ts +21 -0
- package/node_modules/zod/src/v3/tests/nativeEnum.test.ts +87 -0
- package/node_modules/zod/src/v3/tests/nullable.test.ts +42 -0
- package/node_modules/zod/src/v3/tests/number.test.ts +176 -0
- package/node_modules/zod/src/v3/tests/object-augmentation.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/object.test.ts +434 -0
- package/node_modules/zod/src/v3/tests/optional.test.ts +42 -0
- package/node_modules/zod/src/v3/tests/parseUtil.test.ts +23 -0
- package/node_modules/zod/src/v3/tests/parser.test.ts +41 -0
- package/node_modules/zod/src/v3/tests/partials.test.ts +243 -0
- package/node_modules/zod/src/v3/tests/pickomit.test.ts +111 -0
- package/node_modules/zod/src/v3/tests/pipeline.test.ts +29 -0
- package/node_modules/zod/src/v3/tests/preprocess.test.ts +186 -0
- package/node_modules/zod/src/v3/tests/primitive.test.ts +440 -0
- package/node_modules/zod/src/v3/tests/promise.test.ts +90 -0
- package/node_modules/zod/src/v3/tests/readonly.test.ts +194 -0
- package/node_modules/zod/src/v3/tests/record.test.ts +171 -0
- package/node_modules/zod/src/v3/tests/recursive.test.ts +197 -0
- package/node_modules/zod/src/v3/tests/refine.test.ts +313 -0
- package/node_modules/zod/src/v3/tests/safeparse.test.ts +27 -0
- package/node_modules/zod/src/v3/tests/set.test.ts +142 -0
- package/node_modules/zod/src/v3/tests/standard-schema.test.ts +83 -0
- package/node_modules/zod/src/v3/tests/string.test.ts +916 -0
- package/node_modules/zod/src/v3/tests/transformer.test.ts +233 -0
- package/node_modules/zod/src/v3/tests/tuple.test.ts +90 -0
- package/node_modules/zod/src/v3/tests/unions.test.ts +57 -0
- package/node_modules/zod/src/v3/tests/validations.test.ts +133 -0
- package/node_modules/zod/src/v3/tests/void.test.ts +15 -0
- package/node_modules/zod/src/v3/types.ts +5136 -0
- package/node_modules/zod/src/v4/classic/checks.ts +30 -0
- package/node_modules/zod/src/v4/classic/coerce.ts +27 -0
- package/node_modules/zod/src/v4/classic/compat.ts +66 -0
- package/node_modules/zod/src/v4/classic/errors.ts +75 -0
- package/node_modules/zod/src/v4/classic/external.ts +50 -0
- package/node_modules/zod/src/v4/classic/index.ts +5 -0
- package/node_modules/zod/src/v4/classic/iso.ts +90 -0
- package/node_modules/zod/src/v4/classic/parse.ts +33 -0
- package/node_modules/zod/src/v4/classic/schemas.ts +2054 -0
- package/node_modules/zod/src/v4/classic/tests/anyunknown.test.ts +26 -0
- package/node_modules/zod/src/v4/classic/tests/array.test.ts +264 -0
- package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +210 -0
- package/node_modules/zod/src/v4/classic/tests/async-parsing.test.ts +381 -0
- package/node_modules/zod/src/v4/classic/tests/async-refinements.test.ts +68 -0
- package/node_modules/zod/src/v4/classic/tests/base.test.ts +7 -0
- package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +54 -0
- package/node_modules/zod/src/v4/classic/tests/brand.test.ts +63 -0
- package/node_modules/zod/src/v4/classic/tests/catch.test.ts +252 -0
- package/node_modules/zod/src/v4/classic/tests/coalesce.test.ts +20 -0
- package/node_modules/zod/src/v4/classic/tests/coerce.test.ts +160 -0
- package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +352 -0
- package/node_modules/zod/src/v4/classic/tests/custom.test.ts +40 -0
- package/node_modules/zod/src/v4/classic/tests/date.test.ts +31 -0
- package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +296 -0
- package/node_modules/zod/src/v4/classic/tests/default.test.ts +313 -0
- package/node_modules/zod/src/v4/classic/tests/description.test.ts +32 -0
- package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +619 -0
- package/node_modules/zod/src/v4/classic/tests/enum.test.ts +285 -0
- package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +527 -0
- package/node_modules/zod/src/v4/classic/tests/error.test.ts +711 -0
- package/node_modules/zod/src/v4/classic/tests/file.test.ts +91 -0
- package/node_modules/zod/src/v4/classic/tests/firstparty.test.ts +175 -0
- package/node_modules/zod/src/v4/classic/tests/function.test.ts +268 -0
- package/node_modules/zod/src/v4/classic/tests/generics.test.ts +72 -0
- package/node_modules/zod/src/v4/classic/tests/index.test.ts +829 -0
- package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +34 -0
- package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +171 -0
- package/node_modules/zod/src/v4/classic/tests/json.test.ts +108 -0
- package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +227 -0
- package/node_modules/zod/src/v4/classic/tests/literal.test.ts +92 -0
- package/node_modules/zod/src/v4/classic/tests/map.test.ts +196 -0
- package/node_modules/zod/src/v4/classic/tests/nan.test.ts +21 -0
- package/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts +168 -0
- package/node_modules/zod/src/v4/classic/tests/nonoptional.test.ts +86 -0
- package/node_modules/zod/src/v4/classic/tests/nullable.test.ts +22 -0
- package/node_modules/zod/src/v4/classic/tests/number.test.ts +247 -0
- package/node_modules/zod/src/v4/classic/tests/object.test.ts +563 -0
- package/node_modules/zod/src/v4/classic/tests/optional.test.ts +123 -0
- package/node_modules/zod/src/v4/classic/tests/partial.test.ts +147 -0
- package/node_modules/zod/src/v4/classic/tests/pickomit.test.ts +127 -0
- package/node_modules/zod/src/v4/classic/tests/pipe.test.ts +81 -0
- package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +37 -0
- package/node_modules/zod/src/v4/classic/tests/preprocess.test.ts +298 -0
- package/node_modules/zod/src/v4/classic/tests/primitive.test.ts +175 -0
- package/node_modules/zod/src/v4/classic/tests/promise.test.ts +81 -0
- package/node_modules/zod/src/v4/classic/tests/prototypes.test.ts +23 -0
- package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +252 -0
- package/node_modules/zod/src/v4/classic/tests/record.test.ts +342 -0
- package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +356 -0
- package/node_modules/zod/src/v4/classic/tests/refine.test.ts +532 -0
- package/node_modules/zod/src/v4/classic/tests/registries.test.ts +204 -0
- package/node_modules/zod/src/v4/classic/tests/set.test.ts +179 -0
- package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +57 -0
- package/node_modules/zod/src/v4/classic/tests/string-formats.test.ts +109 -0
- package/node_modules/zod/src/v4/classic/tests/string.test.ts +881 -0
- package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +66 -0
- package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +758 -0
- package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +2314 -0
- package/node_modules/zod/src/v4/classic/tests/transform.test.ts +250 -0
- package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +163 -0
- package/node_modules/zod/src/v4/classic/tests/union.test.ts +94 -0
- package/node_modules/zod/src/v4/classic/tests/validations.test.ts +283 -0
- package/node_modules/zod/src/v4/classic/tests/void.test.ts +12 -0
- package/node_modules/zod/src/v4/core/api.ts +1594 -0
- package/node_modules/zod/src/v4/core/checks.ts +1283 -0
- package/node_modules/zod/src/v4/core/config.ts +15 -0
- package/node_modules/zod/src/v4/core/core.ts +134 -0
- package/node_modules/zod/src/v4/core/doc.ts +44 -0
- package/node_modules/zod/src/v4/core/errors.ts +424 -0
- package/node_modules/zod/src/v4/core/function.ts +176 -0
- package/node_modules/zod/src/v4/core/index.ts +15 -0
- package/node_modules/zod/src/v4/core/json-schema.ts +143 -0
- package/node_modules/zod/src/v4/core/parse.ts +94 -0
- package/node_modules/zod/src/v4/core/regexes.ts +135 -0
- package/node_modules/zod/src/v4/core/registries.ts +96 -0
- package/node_modules/zod/src/v4/core/schemas.ts +3842 -0
- package/node_modules/zod/src/v4/core/standard-schema.ts +64 -0
- package/node_modules/zod/src/v4/core/tests/index.test.ts +46 -0
- package/node_modules/zod/src/v4/core/tests/locales/be.test.ts +124 -0
- package/node_modules/zod/src/v4/core/tests/locales/en.test.ts +22 -0
- package/node_modules/zod/src/v4/core/tests/locales/ru.test.ts +128 -0
- package/node_modules/zod/src/v4/core/tests/locales/tr.test.ts +69 -0
- package/node_modules/zod/src/v4/core/to-json-schema.ts +977 -0
- package/node_modules/zod/src/v4/core/util.ts +775 -0
- package/node_modules/zod/src/v4/core/versions.ts +5 -0
- package/node_modules/zod/src/v4/core/zsf.ts +323 -0
- package/node_modules/zod/src/v4/index.ts +4 -0
- package/node_modules/zod/src/v4/locales/ar.ts +125 -0
- package/node_modules/zod/src/v4/locales/az.ts +121 -0
- package/node_modules/zod/src/v4/locales/be.ts +184 -0
- package/node_modules/zod/src/v4/locales/ca.ts +127 -0
- package/node_modules/zod/src/v4/locales/cs.ts +142 -0
- package/node_modules/zod/src/v4/locales/de.ts +124 -0
- package/node_modules/zod/src/v4/locales/en.ts +127 -0
- package/node_modules/zod/src/v4/locales/eo.ts +125 -0
- package/node_modules/zod/src/v4/locales/es.ts +125 -0
- package/node_modules/zod/src/v4/locales/fa.ts +134 -0
- package/node_modules/zod/src/v4/locales/fi.ts +131 -0
- package/node_modules/zod/src/v4/locales/fr-CA.ts +126 -0
- package/node_modules/zod/src/v4/locales/fr.ts +124 -0
- package/node_modules/zod/src/v4/locales/he.ts +125 -0
- package/node_modules/zod/src/v4/locales/hu.ts +126 -0
- package/node_modules/zod/src/v4/locales/id.ts +125 -0
- package/node_modules/zod/src/v4/locales/index.ts +39 -0
- package/node_modules/zod/src/v4/locales/it.ts +125 -0
- package/node_modules/zod/src/v4/locales/ja.ts +122 -0
- package/node_modules/zod/src/v4/locales/kh.ts +126 -0
- package/node_modules/zod/src/v4/locales/ko.ts +131 -0
- package/node_modules/zod/src/v4/locales/mk.ts +127 -0
- package/node_modules/zod/src/v4/locales/ms.ts +124 -0
- package/node_modules/zod/src/v4/locales/nl.ts +126 -0
- package/node_modules/zod/src/v4/locales/no.ts +124 -0
- package/node_modules/zod/src/v4/locales/ota.ts +125 -0
- package/node_modules/zod/src/v4/locales/pl.ts +126 -0
- package/node_modules/zod/src/v4/locales/ps.ts +133 -0
- package/node_modules/zod/src/v4/locales/pt.ts +123 -0
- package/node_modules/zod/src/v4/locales/ru.ts +184 -0
- package/node_modules/zod/src/v4/locales/sl.ts +126 -0
- package/node_modules/zod/src/v4/locales/sv.ts +127 -0
- package/node_modules/zod/src/v4/locales/ta.ts +125 -0
- package/node_modules/zod/src/v4/locales/th.ts +126 -0
- package/node_modules/zod/src/v4/locales/tr.ts +121 -0
- package/node_modules/zod/src/v4/locales/ua.ts +126 -0
- package/node_modules/zod/src/v4/locales/ur.ts +126 -0
- package/node_modules/zod/src/v4/locales/vi.ts +125 -0
- package/node_modules/zod/src/v4/locales/zh-CN.ts +123 -0
- package/node_modules/zod/src/v4/locales/zh-TW.ts +125 -0
- package/node_modules/zod/src/v4/mini/checks.ts +32 -0
- package/node_modules/zod/src/v4/mini/coerce.ts +22 -0
- package/node_modules/zod/src/v4/mini/external.ts +40 -0
- package/node_modules/zod/src/v4/mini/index.ts +3 -0
- package/node_modules/zod/src/v4/mini/iso.ts +62 -0
- package/node_modules/zod/src/v4/mini/parse.ts +1 -0
- package/node_modules/zod/src/v4/mini/schemas.ts +1579 -0
- package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +129 -0
- package/node_modules/zod/src/v4/mini/tests/brand.test.ts +51 -0
- package/node_modules/zod/src/v4/mini/tests/checks.test.ts +144 -0
- package/node_modules/zod/src/v4/mini/tests/computed.test.ts +36 -0
- package/node_modules/zod/src/v4/mini/tests/error.test.ts +22 -0
- package/node_modules/zod/src/v4/mini/tests/functions.test.ts +43 -0
- package/node_modules/zod/src/v4/mini/tests/index.test.ts +871 -0
- package/node_modules/zod/src/v4/mini/tests/number.test.ts +95 -0
- package/node_modules/zod/src/v4/mini/tests/object.test.ts +185 -0
- package/node_modules/zod/src/v4/mini/tests/prototypes.test.ts +43 -0
- package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +275 -0
- package/node_modules/zod/src/v4/mini/tests/string.test.ts +299 -0
- package/node_modules/zod/src/v4-mini/index.ts +1 -0
- package/node_modules/zod/v3/ZodError.cjs +138 -0
- package/node_modules/zod/v3/ZodError.d.cts +164 -0
- package/node_modules/zod/v3/ZodError.d.ts +164 -0
- package/node_modules/zod/v3/ZodError.js +133 -0
- package/node_modules/zod/v3/errors.cjs +17 -0
- package/node_modules/zod/v3/errors.d.cts +5 -0
- package/node_modules/zod/v3/errors.d.ts +5 -0
- package/node_modules/zod/v3/errors.js +9 -0
- package/node_modules/zod/v3/external.cjs +22 -0
- package/node_modules/zod/v3/external.d.cts +6 -0
- package/node_modules/zod/v3/external.d.ts +6 -0
- package/node_modules/zod/v3/external.js +6 -0
- package/node_modules/zod/v3/helpers/enumUtil.cjs +2 -0
- package/node_modules/zod/v3/helpers/enumUtil.d.cts +8 -0
- package/node_modules/zod/v3/helpers/enumUtil.d.ts +8 -0
- package/node_modules/zod/v3/helpers/enumUtil.js +1 -0
- package/node_modules/zod/v3/helpers/errorUtil.cjs +9 -0
- package/node_modules/zod/v3/helpers/errorUtil.d.cts +9 -0
- package/node_modules/zod/v3/helpers/errorUtil.d.ts +9 -0
- package/node_modules/zod/v3/helpers/errorUtil.js +6 -0
- package/node_modules/zod/v3/helpers/parseUtil.cjs +124 -0
- package/node_modules/zod/v3/helpers/parseUtil.d.cts +78 -0
- package/node_modules/zod/v3/helpers/parseUtil.d.ts +78 -0
- package/node_modules/zod/v3/helpers/parseUtil.js +109 -0
- package/node_modules/zod/v3/helpers/partialUtil.cjs +2 -0
- package/node_modules/zod/v3/helpers/partialUtil.d.cts +8 -0
- package/node_modules/zod/v3/helpers/partialUtil.d.ts +8 -0
- package/node_modules/zod/v3/helpers/partialUtil.js +1 -0
- package/node_modules/zod/v3/helpers/typeAliases.cjs +2 -0
- package/node_modules/zod/v3/helpers/typeAliases.d.cts +2 -0
- package/node_modules/zod/v3/helpers/typeAliases.d.ts +2 -0
- package/node_modules/zod/v3/helpers/typeAliases.js +1 -0
- package/node_modules/zod/v3/helpers/util.cjs +137 -0
- package/node_modules/zod/v3/helpers/util.d.cts +85 -0
- package/node_modules/zod/v3/helpers/util.d.ts +85 -0
- package/node_modules/zod/v3/helpers/util.js +133 -0
- package/node_modules/zod/v3/index.cjs +33 -0
- package/node_modules/zod/v3/index.d.cts +4 -0
- package/node_modules/zod/v3/index.d.ts +4 -0
- package/node_modules/zod/v3/index.js +4 -0
- package/node_modules/zod/v3/locales/en.cjs +111 -0
- package/node_modules/zod/v3/locales/en.d.cts +3 -0
- package/node_modules/zod/v3/locales/en.d.ts +3 -0
- package/node_modules/zod/v3/locales/en.js +109 -0
- package/node_modules/zod/v3/standard-schema.cjs +2 -0
- package/node_modules/zod/v3/standard-schema.d.cts +102 -0
- package/node_modules/zod/v3/standard-schema.d.ts +102 -0
- package/node_modules/zod/v3/standard-schema.js +1 -0
- package/node_modules/zod/v3/types.cjs +3775 -0
- package/node_modules/zod/v3/types.d.cts +1031 -0
- package/node_modules/zod/v3/types.d.ts +1031 -0
- package/node_modules/zod/v3/types.js +3693 -0
- package/node_modules/zod/v4/classic/checks.cjs +32 -0
- package/node_modules/zod/v4/classic/checks.d.cts +1 -0
- package/node_modules/zod/v4/classic/checks.d.ts +1 -0
- package/node_modules/zod/v4/classic/checks.js +1 -0
- package/node_modules/zod/v4/classic/coerce.cjs +47 -0
- package/node_modules/zod/v4/classic/coerce.d.cts +17 -0
- package/node_modules/zod/v4/classic/coerce.d.ts +17 -0
- package/node_modules/zod/v4/classic/coerce.js +17 -0
- package/node_modules/zod/v4/classic/compat.cjs +57 -0
- package/node_modules/zod/v4/classic/compat.d.cts +46 -0
- package/node_modules/zod/v4/classic/compat.d.ts +46 -0
- package/node_modules/zod/v4/classic/compat.js +27 -0
- package/node_modules/zod/v4/classic/errors.cjs +67 -0
- package/node_modules/zod/v4/classic/errors.d.cts +30 -0
- package/node_modules/zod/v4/classic/errors.d.ts +30 -0
- package/node_modules/zod/v4/classic/errors.js +41 -0
- package/node_modules/zod/v4/classic/external.cjs +70 -0
- package/node_modules/zod/v4/classic/external.d.cts +13 -0
- package/node_modules/zod/v4/classic/external.d.ts +13 -0
- package/node_modules/zod/v4/classic/external.js +18 -0
- package/node_modules/zod/v4/classic/index.cjs +33 -0
- package/node_modules/zod/v4/classic/index.d.cts +4 -0
- package/node_modules/zod/v4/classic/index.d.ts +4 -0
- package/node_modules/zod/v4/classic/index.js +4 -0
- package/node_modules/zod/v4/classic/iso.cjs +60 -0
- package/node_modules/zod/v4/classic/iso.d.cts +22 -0
- package/node_modules/zod/v4/classic/iso.d.ts +22 -0
- package/node_modules/zod/v4/classic/iso.js +30 -0
- package/node_modules/zod/v4/classic/parse.cjs +32 -0
- package/node_modules/zod/v4/classic/parse.d.cts +23 -0
- package/node_modules/zod/v4/classic/parse.d.ts +23 -0
- package/node_modules/zod/v4/classic/parse.js +6 -0
- package/node_modules/zod/v4/classic/schemas.cjs +1109 -0
- package/node_modules/zod/v4/classic/schemas.d.cts +630 -0
- package/node_modules/zod/v4/classic/schemas.d.ts +630 -0
- package/node_modules/zod/v4/classic/schemas.js +1006 -0
- package/node_modules/zod/v4/core/api.cjs +1039 -0
- package/node_modules/zod/v4/core/api.d.cts +284 -0
- package/node_modules/zod/v4/core/api.d.ts +284 -0
- package/node_modules/zod/v4/core/api.js +906 -0
- package/node_modules/zod/v4/core/checks.cjs +591 -0
- package/node_modules/zod/v4/core/checks.d.cts +278 -0
- package/node_modules/zod/v4/core/checks.d.ts +278 -0
- package/node_modules/zod/v4/core/checks.js +565 -0
- package/node_modules/zod/v4/core/core.cjs +67 -0
- package/node_modules/zod/v4/core/core.d.cts +49 -0
- package/node_modules/zod/v4/core/core.d.ts +49 -0
- package/node_modules/zod/v4/core/core.js +61 -0
- package/node_modules/zod/v4/core/doc.cjs +39 -0
- package/node_modules/zod/v4/core/doc.d.cts +14 -0
- package/node_modules/zod/v4/core/doc.d.ts +14 -0
- package/node_modules/zod/v4/core/doc.js +35 -0
- package/node_modules/zod/v4/core/errors.cjs +226 -0
- package/node_modules/zod/v4/core/errors.d.cts +208 -0
- package/node_modules/zod/v4/core/errors.d.ts +208 -0
- package/node_modules/zod/v4/core/errors.js +195 -0
- package/node_modules/zod/v4/core/function.cjs +102 -0
- package/node_modules/zod/v4/core/function.d.cts +52 -0
- package/node_modules/zod/v4/core/function.d.ts +52 -0
- package/node_modules/zod/v4/core/function.js +75 -0
- package/node_modules/zod/v4/core/index.cjs +44 -0
- package/node_modules/zod/v4/core/index.d.cts +15 -0
- package/node_modules/zod/v4/core/index.d.ts +15 -0
- package/node_modules/zod/v4/core/index.js +15 -0
- package/node_modules/zod/v4/core/json-schema.cjs +2 -0
- package/node_modules/zod/v4/core/json-schema.d.cts +87 -0
- package/node_modules/zod/v4/core/json-schema.d.ts +87 -0
- package/node_modules/zod/v4/core/json-schema.js +1 -0
- package/node_modules/zod/v4/core/parse.cjs +87 -0
- package/node_modules/zod/v4/core/parse.d.cts +25 -0
- package/node_modules/zod/v4/core/parse.d.ts +25 -0
- package/node_modules/zod/v4/core/parse.js +57 -0
- package/node_modules/zod/v4/core/regexes.cjs +103 -0
- package/node_modules/zod/v4/core/regexes.d.cts +62 -0
- package/node_modules/zod/v4/core/regexes.d.ts +62 -0
- package/node_modules/zod/v4/core/regexes.js +95 -0
- package/node_modules/zod/v4/core/registries.cjs +56 -0
- package/node_modules/zod/v4/core/registries.d.cts +35 -0
- package/node_modules/zod/v4/core/registries.d.ts +35 -0
- package/node_modules/zod/v4/core/registries.js +51 -0
- package/node_modules/zod/v4/core/schemas.cjs +1748 -0
- package/node_modules/zod/v4/core/schemas.d.cts +1041 -0
- package/node_modules/zod/v4/core/schemas.d.ts +1041 -0
- package/node_modules/zod/v4/core/schemas.js +1717 -0
- package/node_modules/zod/v4/core/standard-schema.cjs +2 -0
- package/node_modules/zod/v4/core/standard-schema.d.cts +55 -0
- package/node_modules/zod/v4/core/standard-schema.d.ts +55 -0
- package/node_modules/zod/v4/core/standard-schema.js +1 -0
- package/node_modules/zod/v4/core/to-json-schema.cjs +854 -0
- package/node_modules/zod/v4/core/to-json-schema.d.cts +88 -0
- package/node_modules/zod/v4/core/to-json-schema.d.ts +88 -0
- package/node_modules/zod/v4/core/to-json-schema.js +849 -0
- package/node_modules/zod/v4/core/util.cjs +539 -0
- package/node_modules/zod/v4/core/util.d.cts +183 -0
- package/node_modules/zod/v4/core/util.d.ts +183 -0
- package/node_modules/zod/v4/core/util.js +493 -0
- package/node_modules/zod/v4/core/versions.cjs +8 -0
- package/node_modules/zod/v4/core/versions.d.cts +5 -0
- package/node_modules/zod/v4/core/versions.d.ts +5 -0
- package/node_modules/zod/v4/core/versions.js +5 -0
- package/node_modules/zod/v4/index.cjs +22 -0
- package/node_modules/zod/v4/index.d.cts +3 -0
- package/node_modules/zod/v4/index.d.ts +3 -0
- package/node_modules/zod/v4/index.js +3 -0
- package/node_modules/zod/v4/locales/ar.cjs +142 -0
- package/node_modules/zod/v4/locales/ar.d.cts +4 -0
- package/node_modules/zod/v4/locales/ar.d.ts +4 -0
- package/node_modules/zod/v4/locales/ar.js +116 -0
- package/node_modules/zod/v4/locales/az.cjs +141 -0
- package/node_modules/zod/v4/locales/az.d.cts +4 -0
- package/node_modules/zod/v4/locales/az.d.ts +4 -0
- package/node_modules/zod/v4/locales/az.js +115 -0
- package/node_modules/zod/v4/locales/be.cjs +190 -0
- package/node_modules/zod/v4/locales/be.d.cts +4 -0
- package/node_modules/zod/v4/locales/be.d.ts +4 -0
- package/node_modules/zod/v4/locales/be.js +164 -0
- package/node_modules/zod/v4/locales/ca.cjs +144 -0
- package/node_modules/zod/v4/locales/ca.d.cts +4 -0
- package/node_modules/zod/v4/locales/ca.d.ts +4 -0
- package/node_modules/zod/v4/locales/ca.js +118 -0
- package/node_modules/zod/v4/locales/cs.cjs +161 -0
- package/node_modules/zod/v4/locales/cs.d.cts +4 -0
- package/node_modules/zod/v4/locales/cs.d.ts +4 -0
- package/node_modules/zod/v4/locales/cs.js +135 -0
- package/node_modules/zod/v4/locales/de.cjs +142 -0
- package/node_modules/zod/v4/locales/de.d.cts +4 -0
- package/node_modules/zod/v4/locales/de.d.ts +4 -0
- package/node_modules/zod/v4/locales/de.js +116 -0
- package/node_modules/zod/v4/locales/en.cjs +145 -0
- package/node_modules/zod/v4/locales/en.d.cts +5 -0
- package/node_modules/zod/v4/locales/en.d.ts +5 -0
- package/node_modules/zod/v4/locales/en.js +117 -0
- package/node_modules/zod/v4/locales/eo.cjs +144 -0
- package/node_modules/zod/v4/locales/eo.d.cts +5 -0
- package/node_modules/zod/v4/locales/eo.d.ts +5 -0
- package/node_modules/zod/v4/locales/eo.js +116 -0
- package/node_modules/zod/v4/locales/es.cjs +143 -0
- package/node_modules/zod/v4/locales/es.d.cts +4 -0
- package/node_modules/zod/v4/locales/es.d.ts +4 -0
- package/node_modules/zod/v4/locales/es.js +117 -0
- package/node_modules/zod/v4/locales/fa.cjs +148 -0
- package/node_modules/zod/v4/locales/fa.d.cts +4 -0
- package/node_modules/zod/v4/locales/fa.d.ts +4 -0
- package/node_modules/zod/v4/locales/fa.js +122 -0
- package/node_modules/zod/v4/locales/fi.cjs +148 -0
- package/node_modules/zod/v4/locales/fi.d.cts +4 -0
- package/node_modules/zod/v4/locales/fi.d.ts +4 -0
- package/node_modules/zod/v4/locales/fi.js +122 -0
- package/node_modules/zod/v4/locales/fr-CA.cjs +143 -0
- package/node_modules/zod/v4/locales/fr-CA.d.cts +4 -0
- package/node_modules/zod/v4/locales/fr-CA.d.ts +4 -0
- package/node_modules/zod/v4/locales/fr-CA.js +117 -0
- package/node_modules/zod/v4/locales/fr.cjs +142 -0
- package/node_modules/zod/v4/locales/fr.d.cts +4 -0
- package/node_modules/zod/v4/locales/fr.d.ts +4 -0
- package/node_modules/zod/v4/locales/fr.js +116 -0
- package/node_modules/zod/v4/locales/he.cjs +143 -0
- package/node_modules/zod/v4/locales/he.d.cts +4 -0
- package/node_modules/zod/v4/locales/he.d.ts +4 -0
- package/node_modules/zod/v4/locales/he.js +117 -0
- package/node_modules/zod/v4/locales/hu.cjs +143 -0
- package/node_modules/zod/v4/locales/hu.d.cts +4 -0
- package/node_modules/zod/v4/locales/hu.d.ts +4 -0
- package/node_modules/zod/v4/locales/hu.js +117 -0
- package/node_modules/zod/v4/locales/id.cjs +142 -0
- package/node_modules/zod/v4/locales/id.d.cts +4 -0
- package/node_modules/zod/v4/locales/id.d.ts +4 -0
- package/node_modules/zod/v4/locales/id.js +116 -0
- package/node_modules/zod/v4/locales/index.cjs +84 -0
- package/node_modules/zod/v4/locales/index.d.cts +39 -0
- package/node_modules/zod/v4/locales/index.d.ts +39 -0
- package/node_modules/zod/v4/locales/index.js +39 -0
- package/node_modules/zod/v4/locales/it.cjs +143 -0
- package/node_modules/zod/v4/locales/it.d.cts +4 -0
- package/node_modules/zod/v4/locales/it.d.ts +4 -0
- package/node_modules/zod/v4/locales/it.js +117 -0
- package/node_modules/zod/v4/locales/ja.cjs +141 -0
- package/node_modules/zod/v4/locales/ja.d.cts +4 -0
- package/node_modules/zod/v4/locales/ja.d.ts +4 -0
- package/node_modules/zod/v4/locales/ja.js +115 -0
- package/node_modules/zod/v4/locales/kh.cjs +143 -0
- package/node_modules/zod/v4/locales/kh.d.cts +4 -0
- package/node_modules/zod/v4/locales/kh.d.ts +4 -0
- package/node_modules/zod/v4/locales/kh.js +117 -0
- package/node_modules/zod/v4/locales/ko.cjs +147 -0
- package/node_modules/zod/v4/locales/ko.d.cts +4 -0
- package/node_modules/zod/v4/locales/ko.d.ts +4 -0
- package/node_modules/zod/v4/locales/ko.js +121 -0
- package/node_modules/zod/v4/locales/mk.cjs +144 -0
- package/node_modules/zod/v4/locales/mk.d.cts +4 -0
- package/node_modules/zod/v4/locales/mk.d.ts +4 -0
- package/node_modules/zod/v4/locales/mk.js +118 -0
- package/node_modules/zod/v4/locales/ms.cjs +142 -0
- package/node_modules/zod/v4/locales/ms.d.cts +4 -0
- package/node_modules/zod/v4/locales/ms.d.ts +4 -0
- package/node_modules/zod/v4/locales/ms.js +116 -0
- package/node_modules/zod/v4/locales/nl.cjs +143 -0
- package/node_modules/zod/v4/locales/nl.d.cts +4 -0
- package/node_modules/zod/v4/locales/nl.d.ts +4 -0
- package/node_modules/zod/v4/locales/nl.js +117 -0
- package/node_modules/zod/v4/locales/no.cjs +142 -0
- package/node_modules/zod/v4/locales/no.d.cts +4 -0
- package/node_modules/zod/v4/locales/no.d.ts +4 -0
- package/node_modules/zod/v4/locales/no.js +116 -0
- package/node_modules/zod/v4/locales/ota.cjs +143 -0
- package/node_modules/zod/v4/locales/ota.d.cts +4 -0
- package/node_modules/zod/v4/locales/ota.d.ts +4 -0
- package/node_modules/zod/v4/locales/ota.js +117 -0
- package/node_modules/zod/v4/locales/pl.cjs +143 -0
- package/node_modules/zod/v4/locales/pl.d.cts +4 -0
- package/node_modules/zod/v4/locales/pl.d.ts +4 -0
- package/node_modules/zod/v4/locales/pl.js +117 -0
- package/node_modules/zod/v4/locales/ps.cjs +148 -0
- package/node_modules/zod/v4/locales/ps.d.cts +4 -0
- package/node_modules/zod/v4/locales/ps.d.ts +4 -0
- package/node_modules/zod/v4/locales/ps.js +122 -0
- package/node_modules/zod/v4/locales/pt.cjs +142 -0
- package/node_modules/zod/v4/locales/pt.d.cts +4 -0
- package/node_modules/zod/v4/locales/pt.d.ts +4 -0
- package/node_modules/zod/v4/locales/pt.js +116 -0
- package/node_modules/zod/v4/locales/ru.cjs +190 -0
- package/node_modules/zod/v4/locales/ru.d.cts +4 -0
- package/node_modules/zod/v4/locales/ru.d.ts +4 -0
- package/node_modules/zod/v4/locales/ru.js +164 -0
- package/node_modules/zod/v4/locales/sl.cjs +143 -0
- package/node_modules/zod/v4/locales/sl.d.cts +4 -0
- package/node_modules/zod/v4/locales/sl.d.ts +4 -0
- package/node_modules/zod/v4/locales/sl.js +117 -0
- package/node_modules/zod/v4/locales/sv.cjs +144 -0
- package/node_modules/zod/v4/locales/sv.d.cts +4 -0
- package/node_modules/zod/v4/locales/sv.d.ts +4 -0
- package/node_modules/zod/v4/locales/sv.js +118 -0
- package/node_modules/zod/v4/locales/ta.cjs +143 -0
- package/node_modules/zod/v4/locales/ta.d.cts +4 -0
- package/node_modules/zod/v4/locales/ta.d.ts +4 -0
- package/node_modules/zod/v4/locales/ta.js +117 -0
- package/node_modules/zod/v4/locales/th.cjs +143 -0
- package/node_modules/zod/v4/locales/th.d.cts +4 -0
- package/node_modules/zod/v4/locales/th.d.ts +4 -0
- package/node_modules/zod/v4/locales/th.js +117 -0
- package/node_modules/zod/v4/locales/tr.cjs +143 -0
- package/node_modules/zod/v4/locales/tr.d.cts +5 -0
- package/node_modules/zod/v4/locales/tr.d.ts +5 -0
- package/node_modules/zod/v4/locales/tr.js +115 -0
- package/node_modules/zod/v4/locales/ua.cjs +143 -0
- package/node_modules/zod/v4/locales/ua.d.cts +4 -0
- package/node_modules/zod/v4/locales/ua.d.ts +4 -0
- package/node_modules/zod/v4/locales/ua.js +117 -0
- package/node_modules/zod/v4/locales/ur.cjs +143 -0
- package/node_modules/zod/v4/locales/ur.d.cts +4 -0
- package/node_modules/zod/v4/locales/ur.d.ts +4 -0
- package/node_modules/zod/v4/locales/ur.js +117 -0
- package/node_modules/zod/v4/locales/vi.cjs +142 -0
- package/node_modules/zod/v4/locales/vi.d.cts +4 -0
- package/node_modules/zod/v4/locales/vi.d.ts +4 -0
- package/node_modules/zod/v4/locales/vi.js +116 -0
- package/node_modules/zod/v4/locales/zh-CN.cjs +142 -0
- package/node_modules/zod/v4/locales/zh-CN.d.cts +4 -0
- package/node_modules/zod/v4/locales/zh-CN.d.ts +4 -0
- package/node_modules/zod/v4/locales/zh-CN.js +116 -0
- package/node_modules/zod/v4/locales/zh-TW.cjs +143 -0
- package/node_modules/zod/v4/locales/zh-TW.d.cts +4 -0
- package/node_modules/zod/v4/locales/zh-TW.d.ts +4 -0
- package/node_modules/zod/v4/locales/zh-TW.js +117 -0
- package/node_modules/zod/v4/mini/checks.cjs +34 -0
- package/node_modules/zod/v4/mini/checks.d.cts +1 -0
- package/node_modules/zod/v4/mini/checks.d.ts +1 -0
- package/node_modules/zod/v4/mini/checks.js +1 -0
- package/node_modules/zod/v4/mini/coerce.cjs +47 -0
- package/node_modules/zod/v4/mini/coerce.d.cts +7 -0
- package/node_modules/zod/v4/mini/coerce.d.ts +7 -0
- package/node_modules/zod/v4/mini/coerce.js +17 -0
- package/node_modules/zod/v4/mini/external.cjs +62 -0
- package/node_modules/zod/v4/mini/external.d.cts +11 -0
- package/node_modules/zod/v4/mini/external.d.ts +11 -0
- package/node_modules/zod/v4/mini/external.js +13 -0
- package/node_modules/zod/v4/mini/index.cjs +32 -0
- package/node_modules/zod/v4/mini/index.d.cts +3 -0
- package/node_modules/zod/v4/mini/index.d.ts +3 -0
- package/node_modules/zod/v4/mini/index.js +3 -0
- package/node_modules/zod/v4/mini/iso.cjs +60 -0
- package/node_modules/zod/v4/mini/iso.d.cts +22 -0
- package/node_modules/zod/v4/mini/iso.d.ts +22 -0
- package/node_modules/zod/v4/mini/iso.js +30 -0
- package/node_modules/zod/v4/mini/parse.cjs +8 -0
- package/node_modules/zod/v4/mini/parse.d.cts +1 -0
- package/node_modules/zod/v4/mini/parse.d.ts +1 -0
- package/node_modules/zod/v4/mini/parse.js +1 -0
- package/node_modules/zod/v4/mini/schemas.cjs +839 -0
- package/node_modules/zod/v4/mini/schemas.d.cts +356 -0
- package/node_modules/zod/v4/mini/schemas.d.ts +356 -0
- package/node_modules/zod/v4/mini/schemas.js +732 -0
- package/node_modules/zod/v4-mini/index.cjs +17 -0
- package/node_modules/zod/v4-mini/index.d.cts +1 -0
- package/node_modules/zod/v4-mini/index.d.ts +1 -0
- package/node_modules/zod/v4-mini/index.js +1 -0
- package/package.json +99 -104
|
@@ -0,0 +1,1820 @@
|
|
|
1
|
+
import { nextTick, onBeforeUnmount, shallowRef, watch, type Ref } from 'vue';
|
|
2
|
+
import * as echarts from 'echarts';
|
|
3
|
+
import type { ECharts, EChartsOption } from 'echarts';
|
|
4
|
+
import { buildDynamicEchartOption, normalizeDynamicEchartFieldMapping } from './dynamicEchartOption';
|
|
5
|
+
import { buildCartesianResponsiveLayout, buildPieResponsiveLayout } from './chartResponsiveLayout';
|
|
6
|
+
import {
|
|
7
|
+
bindWorkbenchEChartsRuntimeInteractions,
|
|
8
|
+
isWorkbenchHalfDonutPlaceholderData,
|
|
9
|
+
normalizeWorkbenchChartDisplayDefaults as normalizeSharedWorkbenchChartDisplayDefaults,
|
|
10
|
+
prepareWorkbenchEChartsRuntimeOption,
|
|
11
|
+
} from './echartsRuntimeInteractions';
|
|
12
|
+
import type {
|
|
13
|
+
BoxplotSeriesData,
|
|
14
|
+
CandlestickSeriesData,
|
|
15
|
+
DisplayBlockData,
|
|
16
|
+
EchartsScriptData,
|
|
17
|
+
FunnelStagesData,
|
|
18
|
+
GanttTasksData,
|
|
19
|
+
GaugeMetricData,
|
|
20
|
+
GeoGlobeData,
|
|
21
|
+
HeatmapMatrixData,
|
|
22
|
+
MapRegionsData,
|
|
23
|
+
MultiSeriesData,
|
|
24
|
+
NetworkGraphData,
|
|
25
|
+
ParetoSeriesData,
|
|
26
|
+
PieSlicesData,
|
|
27
|
+
RadarMetricsData,
|
|
28
|
+
SankeyFlowData,
|
|
29
|
+
ScatterPointsData,
|
|
30
|
+
TreeHierarchyData,
|
|
31
|
+
TreeNodeData,
|
|
32
|
+
WaterfallStepsData,
|
|
33
|
+
} from '@fses/workbench-card/types';
|
|
34
|
+
import { normalizeChartRendererKey } from './chartRendererRegistry';
|
|
35
|
+
import {
|
|
36
|
+
applyWorkbenchChartThemeToOption,
|
|
37
|
+
readWorkbenchChartThemeTokens,
|
|
38
|
+
resolveWorkbenchChartThemeRoot,
|
|
39
|
+
} from './workbenchChartTheme';
|
|
40
|
+
export { normalizeChartRendererKey } from './chartRendererRegistry';
|
|
41
|
+
|
|
42
|
+
const CHART_COLORS = ['#1f4fd4', '#17a34a', '#d97706', '#9333ea', '#0f766e', '#dc2626', '#0891b2'];
|
|
43
|
+
const DEFAULT_ECHARTS_ROOT_PATH = '/echarts-examples';
|
|
44
|
+
const OFFICIAL_ECHARTS_ROOT_PATH = 'https://echarts.apache.org/examples';
|
|
45
|
+
const GL_REQUIREMENTS = new Set(['echarts-gl']);
|
|
46
|
+
const GL_SERIES_TYPES = new Set(['graphGL', 'bar3D', 'scatter3D', 'line3D', 'lines3D', 'map3D', 'surface']);
|
|
47
|
+
const GL_SCRIPT_PATTERN = /\b(globe|graphGL|bar3D|scatter3D|line3D|lines3D|map3D|surface)\b/;
|
|
48
|
+
const WORKBENCH_METRIC_ROW_CONTEXT_KEY = '__workbenchMetricRowContext';
|
|
49
|
+
const WORKBENCH_BAR_MIN_HEIGHT = 2;
|
|
50
|
+
const WORKBENCH_DONUT_HOVER_LABEL_MAX_FONT_SIZE = 16;
|
|
51
|
+
const WORKBENCH_DONUT_HOVER_GRAPHIC_ID = '__workbench_donut_hover_label__';
|
|
52
|
+
const echartsMapLoadPromises = new Map<string, Promise<void>>();
|
|
53
|
+
|
|
54
|
+
type JQueryCompatRequest<T = unknown> = Promise<T | undefined> & {
|
|
55
|
+
done(callback: (data: T) => void): JQueryCompatRequest<T>;
|
|
56
|
+
fail(callback: (error: unknown) => void): JQueryCompatRequest<T>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
type JQueryCompat = {
|
|
60
|
+
get(url: string, callback?: (data: unknown) => void): JQueryCompatRequest;
|
|
61
|
+
getJSON(url: string, callback?: (data: unknown) => void): JQueryCompatRequest;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type EchartsScriptApp = Record<string, unknown> & {
|
|
65
|
+
config?: Record<string, unknown>;
|
|
66
|
+
configParameters?: Record<string, unknown>;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type EchartsScriptScope = {
|
|
70
|
+
option?: EChartsOption;
|
|
71
|
+
echarts: typeof echarts;
|
|
72
|
+
myChart: ECharts;
|
|
73
|
+
$: JQueryCompat;
|
|
74
|
+
app: EchartsScriptApp;
|
|
75
|
+
ROOT_PATH: string;
|
|
76
|
+
window: Window;
|
|
77
|
+
document: Document;
|
|
78
|
+
fetch: typeof window.fetch;
|
|
79
|
+
Math: Math;
|
|
80
|
+
Date: DateConstructor;
|
|
81
|
+
Array: ArrayConstructor;
|
|
82
|
+
Object: ObjectConstructor;
|
|
83
|
+
Number: NumberConstructor;
|
|
84
|
+
String: StringConstructor;
|
|
85
|
+
Boolean: BooleanConstructor;
|
|
86
|
+
JSON: JSON;
|
|
87
|
+
console: Console;
|
|
88
|
+
setTimeout: typeof window.setTimeout;
|
|
89
|
+
clearTimeout: typeof window.clearTimeout;
|
|
90
|
+
setInterval: typeof window.setInterval;
|
|
91
|
+
clearInterval: typeof window.clearInterval;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
let echartsGlLoadPromise: Promise<void> | null = null;
|
|
95
|
+
const donutHoverCenterBindings = new WeakMap<ECharts, { option: EChartsOption }>();
|
|
96
|
+
|
|
97
|
+
const regionMap = {
|
|
98
|
+
type: 'FeatureCollection',
|
|
99
|
+
features: [
|
|
100
|
+
{ type: 'Feature', properties: { name: '东北' }, geometry: { type: 'Polygon', coordinates: [[[118, 42], [134, 42], [134, 53], [118, 53], [118, 42]]] } },
|
|
101
|
+
{ type: 'Feature', properties: { name: '华北' }, geometry: { type: 'Polygon', coordinates: [[[108, 36], [122, 36], [122, 44], [108, 44], [108, 36]]] } },
|
|
102
|
+
{ type: 'Feature', properties: { name: '华东' }, geometry: { type: 'Polygon', coordinates: [[[116, 28], [124, 28], [124, 36], [116, 36], [116, 28]]] } },
|
|
103
|
+
{ type: 'Feature', properties: { name: '华中' }, geometry: { type: 'Polygon', coordinates: [[[108, 28], [116, 28], [116, 36], [108, 36], [108, 28]]] } },
|
|
104
|
+
{ type: 'Feature', properties: { name: '华南' }, geometry: { type: 'Polygon', coordinates: [[[108, 20], [122, 20], [122, 28], [108, 28], [108, 20]]] } },
|
|
105
|
+
{ type: 'Feature', properties: { name: '西部' }, geometry: { type: 'Polygon', coordinates: [[[78, 28], [108, 28], [108, 48], [78, 48], [78, 28]]] } },
|
|
106
|
+
{ type: 'Feature', properties: { name: '海外' }, geometry: { type: 'Polygon', coordinates: [[[124, 18], [136, 18], [136, 26], [124, 26], [124, 18]]] } },
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
let mapRegistered = false;
|
|
111
|
+
|
|
112
|
+
function ensureMapRegistered() {
|
|
113
|
+
if (mapRegistered && echarts.getMap('workbench-regions')) return;
|
|
114
|
+
echarts.registerMap('workbench-regions', regionMap as never);
|
|
115
|
+
mapRegistered = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function assertRecord(value: unknown, shape: string): asserts value is Record<string, unknown> {
|
|
119
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`图表数据不是对象:${shape}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function assertArray(value: unknown, name: string): asserts value is unknown[] {
|
|
123
|
+
if (!Array.isArray(value)) throw new Error(`图表字段缺失或格式错误:${name}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function objectValue(value: unknown, key: string) {
|
|
127
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
128
|
+
? (value as Record<string, unknown>)[key]
|
|
129
|
+
: undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
133
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function cloneOptionValue<T>(value: T): T {
|
|
137
|
+
if (Array.isArray(value)) return value.map((item) => cloneOptionValue(item)) as T;
|
|
138
|
+
if (isRecord(value)) {
|
|
139
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneOptionValue(item)])) as T;
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function optionSeriesItems(option: EChartsOption): Record<string, unknown>[] {
|
|
145
|
+
const series = objectValue(option, 'series');
|
|
146
|
+
const items = Array.isArray(series) ? series : [series];
|
|
147
|
+
return items.filter(isRecord);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Caps a numeric option while preserving missing values with a readable default.
|
|
152
|
+
* @param value - Candidate option value.
|
|
153
|
+
* @param fallback - Default value used when the option is missing.
|
|
154
|
+
* @param max - Maximum allowed number.
|
|
155
|
+
* @returns Capped numeric value or the original non-number value.
|
|
156
|
+
*/
|
|
157
|
+
function cappedRuntimeNumber(value: unknown, fallback: number, max: number): unknown {
|
|
158
|
+
if (typeof value === 'number' && Number.isFinite(value)) return Math.min(value, max);
|
|
159
|
+
return value === undefined ? fallback : value;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Checks whether a color is explicitly transparent.
|
|
164
|
+
* @param value - Candidate color option.
|
|
165
|
+
* @returns True when the color should not receive visible bar fallbacks.
|
|
166
|
+
*/
|
|
167
|
+
function isTransparentRuntimeColor(value: unknown): boolean {
|
|
168
|
+
if (typeof value !== 'string') return false;
|
|
169
|
+
const normalized = value.replace(/\s+/g, '').toLowerCase();
|
|
170
|
+
return normalized === 'transparent' || normalized === 'rgba(0,0,0,0)' || /rgba\([^,]+,[^,]+,[^,]+,0\)/.test(normalized);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Checks whether a bar series is only used as an invisible layout helper.
|
|
175
|
+
* @param series - ECharts series option.
|
|
176
|
+
* @returns True for transparent helper bars such as waterfall offsets.
|
|
177
|
+
*/
|
|
178
|
+
function isTransparentRuntimeBarSeries(series: Record<string, unknown>): boolean {
|
|
179
|
+
const itemStyle = objectValue(series, 'itemStyle');
|
|
180
|
+
return isTransparentRuntimeColor(objectValue(series, 'color'))
|
|
181
|
+
|| isTransparentRuntimeColor(objectValue(itemStyle, 'color'));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Checks whether a pie radius value represents a visible inner hole.
|
|
186
|
+
* @param value - Inner radius option from ECharts pie series.
|
|
187
|
+
* @returns True when the inner radius is greater than zero.
|
|
188
|
+
*/
|
|
189
|
+
function hasRuntimeInnerRadius(value: unknown): boolean {
|
|
190
|
+
if (typeof value === 'number') return value > 0;
|
|
191
|
+
if (typeof value !== 'string') return false;
|
|
192
|
+
const normalized = value.trim();
|
|
193
|
+
if (!normalized || normalized === '0' || normalized === '0%') return false;
|
|
194
|
+
const numeric = Number.parseFloat(normalized);
|
|
195
|
+
return Number.isFinite(numeric) && numeric > 0;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Checks whether a pie series is rendered as a donut with a center area.
|
|
200
|
+
* @param series - ECharts series option.
|
|
201
|
+
* @returns True for donut/ring pie series.
|
|
202
|
+
*/
|
|
203
|
+
function isRuntimeDonutSeries(series: Record<string, unknown>): boolean {
|
|
204
|
+
if (series.type !== 'pie') return false;
|
|
205
|
+
const radius = series.radius;
|
|
206
|
+
return Array.isArray(radius) && hasRuntimeInnerRadius(radius[0]);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Keeps donut hover labels centered in the ring instead of floating around slices.
|
|
211
|
+
* @param series - ECharts series option.
|
|
212
|
+
* @returns Donut series with centered, bounded emphasis label typography.
|
|
213
|
+
*/
|
|
214
|
+
function withReadablePieHoverLabel(series: Record<string, unknown>): Record<string, unknown> {
|
|
215
|
+
if (!isRuntimeDonutSeries(series)) return series;
|
|
216
|
+
const seriesLabel = objectValue(series, 'label');
|
|
217
|
+
const seriesLabelLine = objectValue(series, 'labelLine');
|
|
218
|
+
const emphasis = objectValue(series, 'emphasis');
|
|
219
|
+
const emphasisRecord = isRecord(emphasis) ? emphasis : {};
|
|
220
|
+
const label = objectValue(emphasisRecord, 'label');
|
|
221
|
+
const labelRecord = isRecord(label) ? label : {};
|
|
222
|
+
const {
|
|
223
|
+
width: _seriesLabelWidth,
|
|
224
|
+
overflow: _seriesLabelOverflow,
|
|
225
|
+
ellipsis: _seriesLabelEllipsis,
|
|
226
|
+
distance: _seriesLabelDistance,
|
|
227
|
+
distanceToLabelLine: _seriesLabelDistanceToLabelLine,
|
|
228
|
+
alignTo: _seriesLabelAlignTo,
|
|
229
|
+
edgeDistance: _seriesLabelEdgeDistance,
|
|
230
|
+
bleedMargin: _seriesLabelBleedMargin,
|
|
231
|
+
...centerSeriesLabel
|
|
232
|
+
} = isRecord(seriesLabel) ? seriesLabel : {};
|
|
233
|
+
const {
|
|
234
|
+
width: _labelWidth,
|
|
235
|
+
overflow: _labelOverflow,
|
|
236
|
+
ellipsis: _labelEllipsis,
|
|
237
|
+
distance: _labelDistance,
|
|
238
|
+
distanceToLabelLine: _labelDistanceToLabelLine,
|
|
239
|
+
alignTo: _labelAlignTo,
|
|
240
|
+
edgeDistance: _labelEdgeDistance,
|
|
241
|
+
bleedMargin: _labelBleedMargin,
|
|
242
|
+
...centerLabel
|
|
243
|
+
} = labelRecord;
|
|
244
|
+
return {
|
|
245
|
+
...series,
|
|
246
|
+
label: {
|
|
247
|
+
...centerSeriesLabel,
|
|
248
|
+
show: false,
|
|
249
|
+
position: 'center',
|
|
250
|
+
align: 'center',
|
|
251
|
+
verticalAlign: 'middle',
|
|
252
|
+
distance: 0,
|
|
253
|
+
offset: [0, 0],
|
|
254
|
+
rotate: 0,
|
|
255
|
+
},
|
|
256
|
+
labelLine: {
|
|
257
|
+
...(isRecord(seriesLabelLine) ? seriesLabelLine : {}),
|
|
258
|
+
show: false,
|
|
259
|
+
},
|
|
260
|
+
labelLayout: {
|
|
261
|
+
hideOverlap: false,
|
|
262
|
+
},
|
|
263
|
+
emphasis: {
|
|
264
|
+
...emphasisRecord,
|
|
265
|
+
label: {
|
|
266
|
+
...centerLabel,
|
|
267
|
+
show: false,
|
|
268
|
+
position: 'center',
|
|
269
|
+
align: 'center',
|
|
270
|
+
verticalAlign: 'middle',
|
|
271
|
+
distance: 0,
|
|
272
|
+
offset: [0, 0],
|
|
273
|
+
rotate: 0,
|
|
274
|
+
fontSize: cappedRuntimeNumber(centerLabel.fontSize, 14, WORKBENCH_DONUT_HOVER_LABEL_MAX_FONT_SIZE),
|
|
275
|
+
fontWeight: centerLabel.fontWeight ?? 600,
|
|
276
|
+
lineHeight: cappedRuntimeNumber(centerLabel.lineHeight, 20, 22),
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Gives non-zero bar values a visible footprint in compressed comparison charts.
|
|
284
|
+
* @param series - ECharts series option.
|
|
285
|
+
* @returns Bar series with a minimum visible height when appropriate.
|
|
286
|
+
*/
|
|
287
|
+
function withVisibleBarMinimum(series: Record<string, unknown>): Record<string, unknown> {
|
|
288
|
+
const coordinateSystem = typeof series.coordinateSystem === 'string' ? series.coordinateSystem : '';
|
|
289
|
+
if (
|
|
290
|
+
series.type !== 'bar'
|
|
291
|
+
|| (coordinateSystem && coordinateSystem !== 'cartesian2d')
|
|
292
|
+
|| series.barMinHeight !== undefined
|
|
293
|
+
|| isTransparentRuntimeBarSeries(series)
|
|
294
|
+
) return series;
|
|
295
|
+
return {
|
|
296
|
+
...series,
|
|
297
|
+
barMinHeight: WORKBENCH_BAR_MIN_HEIGHT,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Applies workbench-card display defaults to all ECharts options before rendering.
|
|
303
|
+
* @param option - ECharts option from generated, materialized, or script renderers.
|
|
304
|
+
* @returns Option with generic readability safeguards.
|
|
305
|
+
*/
|
|
306
|
+
function normalizeWorkbenchChartDisplayDefaults(option: EChartsOption): EChartsOption {
|
|
307
|
+
const series = objectValue(option, 'series');
|
|
308
|
+
if (!Array.isArray(series) && !isRecord(series)) return option;
|
|
309
|
+
const normalizeSeries = (item: unknown) => (
|
|
310
|
+
isRecord(item) ? withReadablePieHoverLabel(withVisibleBarMinimum(item)) : item
|
|
311
|
+
);
|
|
312
|
+
return {
|
|
313
|
+
...option,
|
|
314
|
+
series: Array.isArray(series) ? series.map(normalizeSeries) : normalizeSeries(series),
|
|
315
|
+
} as EChartsOption;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Reads one series option as a record by index.
|
|
320
|
+
* @param option - Runtime ECharts option.
|
|
321
|
+
* @param index - Series index from ECharts event params.
|
|
322
|
+
* @returns Series option when present.
|
|
323
|
+
*/
|
|
324
|
+
function runtimeSeriesAt(option: EChartsOption, index: number): Record<string, unknown> | null {
|
|
325
|
+
const series = objectValue(option, 'series');
|
|
326
|
+
const item = Array.isArray(series) ? series[index] : index === 0 ? series : undefined;
|
|
327
|
+
return isRecord(item) ? item : null;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Converts an ECharts center coordinate into pixels.
|
|
332
|
+
* @param value - Center coordinate, number or percentage string.
|
|
333
|
+
* @param size - Chart width or height.
|
|
334
|
+
* @returns Pixel coordinate.
|
|
335
|
+
*/
|
|
336
|
+
function chartCenterCoordinate(value: unknown, size: number): number {
|
|
337
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
338
|
+
if (typeof value === 'string') {
|
|
339
|
+
const text = value.trim();
|
|
340
|
+
if (text.endsWith('%')) {
|
|
341
|
+
const percent = Number.parseFloat(text);
|
|
342
|
+
if (Number.isFinite(percent)) return size * percent / 100;
|
|
343
|
+
}
|
|
344
|
+
const numeric = Number.parseFloat(text);
|
|
345
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
346
|
+
}
|
|
347
|
+
return size / 2;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Converts a pie radius value into pixels.
|
|
352
|
+
* @param value - Radius coordinate, number or percentage string.
|
|
353
|
+
* @param chart - Current ECharts instance.
|
|
354
|
+
* @returns Pixel radius.
|
|
355
|
+
*/
|
|
356
|
+
function chartRadiusCoordinate(value: unknown, chart: ECharts): number {
|
|
357
|
+
const base = Math.min(chart.getWidth(), chart.getHeight()) / 2;
|
|
358
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
359
|
+
if (typeof value === 'string') {
|
|
360
|
+
const text = value.trim();
|
|
361
|
+
if (text.endsWith('%')) {
|
|
362
|
+
const percent = Number.parseFloat(text);
|
|
363
|
+
if (Number.isFinite(percent)) return base * percent / 100;
|
|
364
|
+
}
|
|
365
|
+
const numeric = Number.parseFloat(text);
|
|
366
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
367
|
+
}
|
|
368
|
+
return base * 0.42;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Resolves the center and text width available for a donut hover label.
|
|
373
|
+
* @param series - Donut series option.
|
|
374
|
+
* @param chart - Current ECharts instance.
|
|
375
|
+
* @returns Pixel center and safe text width.
|
|
376
|
+
*/
|
|
377
|
+
function donutHoverCenterGeometry(series: Record<string, unknown>, chart: ECharts): { x: number; y: number; width: number } {
|
|
378
|
+
const center = Array.isArray(series.center) ? series.center : ['50%', '50%'];
|
|
379
|
+
const radius = Array.isArray(series.radius) ? series.radius : [];
|
|
380
|
+
const innerRadius = chartRadiusCoordinate(radius[0], chart);
|
|
381
|
+
return {
|
|
382
|
+
x: chartCenterCoordinate(center[0], chart.getWidth()),
|
|
383
|
+
y: chartCenterCoordinate(center[1], chart.getHeight()),
|
|
384
|
+
width: Math.max(72, Math.floor(innerRadius * 2 - 12)),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Writes the centered donut hover label with ECharts graphic so old label layouts cannot pull it outside the ring.
|
|
390
|
+
* @param chart - Current ECharts instance.
|
|
391
|
+
* @param option - Runtime ECharts option used by the chart.
|
|
392
|
+
* @param seriesIndex - Hovered series index.
|
|
393
|
+
* @param label - Hover label text.
|
|
394
|
+
*/
|
|
395
|
+
function setDonutHoverCenterLabel(chart: ECharts, option: EChartsOption, seriesIndex: number, label: string): void {
|
|
396
|
+
const series = runtimeSeriesAt(option, seriesIndex);
|
|
397
|
+
if (!series || !isRuntimeDonutSeries(series) || !label.trim()) return;
|
|
398
|
+
const geometry = donutHoverCenterGeometry(series, chart);
|
|
399
|
+
chart.setOption({
|
|
400
|
+
graphic: [{
|
|
401
|
+
id: WORKBENCH_DONUT_HOVER_GRAPHIC_ID,
|
|
402
|
+
type: 'text',
|
|
403
|
+
x: geometry.x,
|
|
404
|
+
y: geometry.y,
|
|
405
|
+
z: 100,
|
|
406
|
+
silent: true,
|
|
407
|
+
style: {
|
|
408
|
+
text: label.trim(),
|
|
409
|
+
fill: '#1f2937',
|
|
410
|
+
fontSize: WORKBENCH_DONUT_HOVER_LABEL_MAX_FONT_SIZE,
|
|
411
|
+
fontWeight: 600,
|
|
412
|
+
lineHeight: 22,
|
|
413
|
+
width: geometry.width,
|
|
414
|
+
overflow: 'break',
|
|
415
|
+
align: 'center',
|
|
416
|
+
verticalAlign: 'middle',
|
|
417
|
+
},
|
|
418
|
+
}],
|
|
419
|
+
} as EChartsOption);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Clears the runtime graphic used for donut hover labels.
|
|
424
|
+
* @param chart - Current ECharts instance.
|
|
425
|
+
*/
|
|
426
|
+
function clearDonutHoverCenterLabel(chart: ECharts): void {
|
|
427
|
+
chart.setOption({
|
|
428
|
+
graphic: [{
|
|
429
|
+
id: WORKBENCH_DONUT_HOVER_GRAPHIC_ID,
|
|
430
|
+
$action: 'remove',
|
|
431
|
+
}],
|
|
432
|
+
} as EChartsOption);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Binds generic workbench-card donut hover behavior after the final runtime option is set.
|
|
437
|
+
* @param chart - Current ECharts instance.
|
|
438
|
+
* @param option - Final runtime ECharts option.
|
|
439
|
+
*/
|
|
440
|
+
function bindDonutHoverCenterLabel(chart: ECharts, option: EChartsOption): void {
|
|
441
|
+
if (!optionSeriesItems(option).some(isRuntimeDonutSeries)) return;
|
|
442
|
+
const existing = donutHoverCenterBindings.get(chart);
|
|
443
|
+
if (existing) {
|
|
444
|
+
existing.option = option;
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
const binding = { option };
|
|
448
|
+
donutHoverCenterBindings.set(chart, binding);
|
|
449
|
+
chart.on('mouseover', (params: unknown) => {
|
|
450
|
+
const eventParams = params as { seriesType?: string; seriesIndex?: number; name?: unknown; data?: unknown };
|
|
451
|
+
if (eventParams.seriesType !== 'pie' || typeof eventParams.seriesIndex !== 'number') return;
|
|
452
|
+
const dataName = objectValue(eventParams.data, 'name');
|
|
453
|
+
const label = typeof eventParams.name === 'string' && eventParams.name.trim()
|
|
454
|
+
? eventParams.name
|
|
455
|
+
: typeof dataName === 'string'
|
|
456
|
+
? dataName
|
|
457
|
+
: '';
|
|
458
|
+
setDonutHoverCenterLabel(chart, binding.option, eventParams.seriesIndex, label);
|
|
459
|
+
});
|
|
460
|
+
chart.on('mouseout', (params: unknown) => {
|
|
461
|
+
const eventParams = params as { seriesType?: string };
|
|
462
|
+
if (eventParams.seriesType === 'pie') clearDonutHoverCenterLabel(chart);
|
|
463
|
+
});
|
|
464
|
+
chart.on('globalout', () => clearDonutHoverCenterLabel(chart));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function pieLegendLabelsFromOption(option: EChartsOption): string[] {
|
|
468
|
+
const seriesItems = optionSeriesItems(option);
|
|
469
|
+
if (seriesItems.length === 0 || !seriesItems.every((series) => series.type === 'pie')) return [];
|
|
470
|
+
return seriesItems.flatMap((series) => {
|
|
471
|
+
const data = series.data;
|
|
472
|
+
if (!Array.isArray(data)) return [];
|
|
473
|
+
return data.flatMap((item) => (
|
|
474
|
+
isRecord(item) && typeof item.name === 'string' && item.name.trim()
|
|
475
|
+
? [item.name.trim()]
|
|
476
|
+
: []
|
|
477
|
+
));
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function legendWithRuntimeLabels(legend: unknown, labels: string[]): unknown {
|
|
482
|
+
if (labels.length === 0) return legend;
|
|
483
|
+
if (Array.isArray(legend)) {
|
|
484
|
+
return legend.map((item, index) => (
|
|
485
|
+
index === 0 && isRecord(item) ? { ...item, data: labels } : item
|
|
486
|
+
));
|
|
487
|
+
}
|
|
488
|
+
if (legend === false) return legend;
|
|
489
|
+
return isRecord(legend) ? { ...legend, data: labels } : { data: labels };
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function normalizeEchartsOptionPieLegend(option: EChartsOption): EChartsOption {
|
|
493
|
+
const labels = pieLegendLabelsFromOption(option);
|
|
494
|
+
if (labels.length === 0) return option;
|
|
495
|
+
const next = cloneOptionValue(option) as Record<string, unknown>;
|
|
496
|
+
next.legend = legendWithRuntimeLabels(next.legend, labels);
|
|
497
|
+
return next as EChartsOption;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* 移除官方示例模板内置的图表标题和工具栏,避免与工作台卡片标题、操作区重复。
|
|
502
|
+
* @param option - 原始 ECharts option。
|
|
503
|
+
* @returns 不含模板标题与 toolbox 的运行时 option。
|
|
504
|
+
*/
|
|
505
|
+
function removeRuntimeEchartsChrome<T>(option: T): T {
|
|
506
|
+
if (!isRecord(option)) return option;
|
|
507
|
+
const optionRecord = option;
|
|
508
|
+
if (!Object.prototype.hasOwnProperty.call(optionRecord, 'title') && !Object.prototype.hasOwnProperty.call(optionRecord, 'toolbox')) {
|
|
509
|
+
return option;
|
|
510
|
+
}
|
|
511
|
+
const next = cloneOptionValue(option) as Record<string, unknown>;
|
|
512
|
+
delete next.title;
|
|
513
|
+
delete next.toolbox;
|
|
514
|
+
return next as T;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* 判断 ECharts 类目轴是否已经包含运行时标签。
|
|
519
|
+
* @param axis - xAxis 配置。
|
|
520
|
+
* @returns 已有非空 data 数组时返回 true。
|
|
521
|
+
*/
|
|
522
|
+
function axisHasCategoryData(axis: unknown): boolean {
|
|
523
|
+
const firstAxis = Array.isArray(axis) ? axis.find(isRecord) : axis;
|
|
524
|
+
return isRecord(firstAxis) && Array.isArray(firstAxis.data) && firstAxis.data.length > 0;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* 从协议数据中读取 X 轴类目标签。
|
|
529
|
+
* @param payload - protocolData 或 dataBinding.dataPayload。
|
|
530
|
+
* @returns 可渲染的类目标签。
|
|
531
|
+
*/
|
|
532
|
+
function categoryLabelsFromProtocolPayload(payload: unknown): string[] {
|
|
533
|
+
if (!isRecord(payload)) return [];
|
|
534
|
+
const categories = payload.categories;
|
|
535
|
+
const xAxis = isRecord(categories) ? categories.xAxis : undefined;
|
|
536
|
+
if (!Array.isArray(xAxis)) return [];
|
|
537
|
+
return xAxis.map((item, index) => {
|
|
538
|
+
const label = String(item ?? '').trim();
|
|
539
|
+
return label || `项 ${index + 1}`;
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* 从渲染数据中读取可用于恢复类目轴的协议标签。
|
|
545
|
+
* @param data - 当前卡片渲染数据。
|
|
546
|
+
* @returns 类目标签。
|
|
547
|
+
*/
|
|
548
|
+
function categoryLabelsFromRendererData(data: DisplayBlockData): string[] {
|
|
549
|
+
const directLabels = categoryLabelsFromProtocolPayload(objectValue(data, 'protocolData'));
|
|
550
|
+
if (directLabels.length > 0) return directLabels;
|
|
551
|
+
const dataBinding = objectValue(data, 'dataBinding');
|
|
552
|
+
return categoryLabelsFromProtocolPayload(objectValue(dataBinding, 'dataPayload'));
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* 补齐历史缓存中缺失的 ECharts 类目轴,避免浏览器回退显示 0..N 下标。
|
|
557
|
+
* @param option - 原始 ECharts option。
|
|
558
|
+
* @param data - 当前卡片渲染数据。
|
|
559
|
+
* @returns 带运行时类目轴的 option。
|
|
560
|
+
*/
|
|
561
|
+
function recoverMissingCartesianCategoryAxis(option: EChartsOption, data: DisplayBlockData): EChartsOption {
|
|
562
|
+
const optionRecord = option as Record<string, unknown>;
|
|
563
|
+
const xAxis = optionRecord.xAxis;
|
|
564
|
+
if ((!Array.isArray(xAxis) && !isRecord(xAxis)) || axisHasCategoryData(xAxis)) return option;
|
|
565
|
+
const labels = categoryLabelsFromRendererData(data);
|
|
566
|
+
if (labels.length === 0) return option;
|
|
567
|
+
const next = cloneOptionValue(option) as Record<string, unknown>;
|
|
568
|
+
const withLabels = (axisItem: unknown) => (
|
|
569
|
+
isRecord(axisItem)
|
|
570
|
+
? { ...axisItem, type: typeof axisItem.type === 'string' ? axisItem.type : 'category', data: labels }
|
|
571
|
+
: axisItem
|
|
572
|
+
);
|
|
573
|
+
next.xAxis = Array.isArray(xAxis)
|
|
574
|
+
? xAxis.map((axisItem, index) => (index === 0 ? withLabels(axisItem) : axisItem))
|
|
575
|
+
: withLabels(xAxis);
|
|
576
|
+
return next as EChartsOption;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* 判断 series 是否不依赖 ECharts 外部坐标系。
|
|
581
|
+
* @param series - ECharts series 配置。
|
|
582
|
+
* @returns 饼图、雷达图、漏斗图和仪表盘返回 true。
|
|
583
|
+
*/
|
|
584
|
+
function isCoordinateFreeRuntimeSeries(series: Record<string, unknown>): boolean {
|
|
585
|
+
return series.type === 'pie'
|
|
586
|
+
|| series.type === 'radar'
|
|
587
|
+
|| series.type === 'funnel'
|
|
588
|
+
|| series.type === 'gauge';
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* 移除非坐标图从官方模板继承到的坐标系索引。
|
|
593
|
+
* @param series - ECharts series 配置。
|
|
594
|
+
* @returns 可直接渲染的 series 配置。
|
|
595
|
+
*/
|
|
596
|
+
function sanitizeCoordinateFreeRuntimeSeries(series: Record<string, unknown>): Record<string, unknown> {
|
|
597
|
+
if (!isCoordinateFreeRuntimeSeries(series)) return series;
|
|
598
|
+
const {
|
|
599
|
+
coordinateSystem: _coordinateSystem,
|
|
600
|
+
xAxisIndex: _xAxisIndex,
|
|
601
|
+
yAxisIndex: _yAxisIndex,
|
|
602
|
+
gridIndex: _gridIndex,
|
|
603
|
+
calendarIndex: _calendarIndex,
|
|
604
|
+
matrixIndex: _matrixIndex,
|
|
605
|
+
polarIndex: _polarIndex,
|
|
606
|
+
geoIndex: _geoIndex,
|
|
607
|
+
bmapIndex: _bmapIndex,
|
|
608
|
+
...rest
|
|
609
|
+
} = series;
|
|
610
|
+
return rest;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* 清理最终 echartsOption 中非坐标图不需要的坐标组件,避免 ECharts 访问缺失坐标系时报错。
|
|
615
|
+
* @param option - 原始 ECharts option。
|
|
616
|
+
* @returns 清理后的 ECharts option。
|
|
617
|
+
*/
|
|
618
|
+
function sanitizeCoordinateFreeRuntimeOption(option: EChartsOption): EChartsOption {
|
|
619
|
+
const rawSeries = objectValue(option, 'series');
|
|
620
|
+
const hasSeriesArray = Array.isArray(rawSeries);
|
|
621
|
+
const seriesItems = hasSeriesArray
|
|
622
|
+
? rawSeries.filter(isRecord)
|
|
623
|
+
: isRecord(rawSeries)
|
|
624
|
+
? [rawSeries]
|
|
625
|
+
: [];
|
|
626
|
+
const hasInvalidSeriesItems = hasSeriesArray && seriesItems.length !== rawSeries.length;
|
|
627
|
+
const hasCoordinateFreeSeries = seriesItems.some(isCoordinateFreeRuntimeSeries);
|
|
628
|
+
if (seriesItems.length === 0) {
|
|
629
|
+
if (!hasInvalidSeriesItems) return option;
|
|
630
|
+
const next = cloneOptionValue(option) as Record<string, unknown>;
|
|
631
|
+
next.series = [];
|
|
632
|
+
return next as EChartsOption;
|
|
633
|
+
}
|
|
634
|
+
if (!hasInvalidSeriesItems && !hasCoordinateFreeSeries) return option;
|
|
635
|
+
|
|
636
|
+
const next = cloneOptionValue(option) as Record<string, unknown>;
|
|
637
|
+
const sanitizedSeries = hasCoordinateFreeSeries
|
|
638
|
+
? seriesItems.map(sanitizeCoordinateFreeRuntimeSeries)
|
|
639
|
+
: seriesItems;
|
|
640
|
+
next.series = hasSeriesArray ? sanitizedSeries : sanitizedSeries[0];
|
|
641
|
+
|
|
642
|
+
if (hasCoordinateFreeSeries && sanitizedSeries.every(isCoordinateFreeRuntimeSeries)) {
|
|
643
|
+
delete next.xAxis;
|
|
644
|
+
delete next.yAxis;
|
|
645
|
+
delete next.grid;
|
|
646
|
+
delete next.calendar;
|
|
647
|
+
delete next.matrix;
|
|
648
|
+
delete next.polar;
|
|
649
|
+
delete next.geo;
|
|
650
|
+
delete next.bmap;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
return next as EChartsOption;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* 判断 ECharts option 是否使用极坐标系。
|
|
658
|
+
* @param option - 候选 ECharts option。
|
|
659
|
+
* @returns 存在 polar 组件或 polar series 时返回 true。
|
|
660
|
+
*/
|
|
661
|
+
function isPolarRuntimeOption(option: EChartsOption): boolean {
|
|
662
|
+
if (objectValue(option, 'polar') !== undefined || objectValue(option, 'angleAxis') !== undefined || objectValue(option, 'radiusAxis') !== undefined) {
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
return optionSeriesItems(option).some((series) => series.coordinateSystem === 'polar');
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* 移除极坐标物化卡片中误继承的笛卡尔坐标组件。
|
|
670
|
+
* @param option - 候选 ECharts option。
|
|
671
|
+
* @returns 极坐标运行时 option。
|
|
672
|
+
*/
|
|
673
|
+
function sanitizePolarRuntimeOption(option: EChartsOption): EChartsOption {
|
|
674
|
+
if (!isPolarRuntimeOption(option)) return option;
|
|
675
|
+
const optionRecord = option as Record<string, unknown>;
|
|
676
|
+
if (
|
|
677
|
+
!Object.prototype.hasOwnProperty.call(optionRecord, 'xAxis')
|
|
678
|
+
&& !Object.prototype.hasOwnProperty.call(optionRecord, 'yAxis')
|
|
679
|
+
&& !Object.prototype.hasOwnProperty.call(optionRecord, 'grid')
|
|
680
|
+
) {
|
|
681
|
+
return option;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const next = cloneOptionValue(option) as Record<string, unknown>;
|
|
685
|
+
delete next.xAxis;
|
|
686
|
+
delete next.yAxis;
|
|
687
|
+
delete next.grid;
|
|
688
|
+
return next as EChartsOption;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* 归一化持久化 echartsOption 的运行时渲染配置。
|
|
693
|
+
* @param option - 原始 ECharts option。
|
|
694
|
+
* @param data - 当前卡片渲染数据。
|
|
695
|
+
* @returns 可直接交给 ECharts 渲染的 option。
|
|
696
|
+
*/
|
|
697
|
+
/**
|
|
698
|
+
* Reads metric row contexts carried by workbench runtime metric payloads.
|
|
699
|
+
* @param data - Current renderer data.
|
|
700
|
+
* @returns Row contexts aligned with rendered series data items.
|
|
701
|
+
*/
|
|
702
|
+
function runtimeMetricRowContexts(data: DisplayBlockData): Record<string, unknown>[] {
|
|
703
|
+
const dataBinding = objectValue(data, 'dataBinding');
|
|
704
|
+
const dataBindingPayload = objectValue(dataBinding, 'dataPayload');
|
|
705
|
+
const dataBindingPayloadExtension = objectValue(dataBindingPayload, 'extension');
|
|
706
|
+
const protocolData = objectValue(data, 'protocolData');
|
|
707
|
+
const protocolDataExtension = objectValue(protocolData, 'extension');
|
|
708
|
+
for (const context of [
|
|
709
|
+
objectValue(data, 'metric_context'),
|
|
710
|
+
objectValue(data, 'metricContext'),
|
|
711
|
+
objectValue(dataBinding, 'metric_context'),
|
|
712
|
+
objectValue(dataBinding, 'metricContext'),
|
|
713
|
+
objectValue(dataBindingPayload, 'metric_context'),
|
|
714
|
+
objectValue(dataBindingPayloadExtension, 'metric_context'),
|
|
715
|
+
objectValue(protocolData, 'metric_context'),
|
|
716
|
+
objectValue(protocolDataExtension, 'metric_context'),
|
|
717
|
+
]) {
|
|
718
|
+
const rows = objectValue(context, 'row_contexts');
|
|
719
|
+
if (Array.isArray(rows)) return rows.filter(isRecord);
|
|
720
|
+
}
|
|
721
|
+
return [];
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Converts an arbitrary ECharts or metric context value into a comparable label.
|
|
726
|
+
* @param value - Candidate display value.
|
|
727
|
+
* @returns Trimmed display label.
|
|
728
|
+
*/
|
|
729
|
+
function metricContextLabel(value: unknown): string {
|
|
730
|
+
if (value === null || value === undefined) return '';
|
|
731
|
+
if (typeof value === 'string') return value.trim();
|
|
732
|
+
if (typeof value === 'number' || typeof value === 'boolean') return String(value);
|
|
733
|
+
try {
|
|
734
|
+
return JSON.stringify(value);
|
|
735
|
+
} catch {
|
|
736
|
+
return '';
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Reads the typed storage value payload from one row-context dimension value.
|
|
742
|
+
* @param value - Candidate storage value.
|
|
743
|
+
* @returns Raw storage value when present.
|
|
744
|
+
*/
|
|
745
|
+
function metricContextStorageRawValue(value: unknown): unknown {
|
|
746
|
+
const record = isRecord(value) ? value : null;
|
|
747
|
+
if (!record || !Object.prototype.hasOwnProperty.call(record, 'value')) return undefined;
|
|
748
|
+
return record.value;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Reads labels that can identify a metric row context across chart renderers.
|
|
753
|
+
* @param rowContext - Runtime metric row context.
|
|
754
|
+
* @returns Comparable dimension labels for this row context.
|
|
755
|
+
*/
|
|
756
|
+
function metricRowContextLabels(rowContext: Record<string, unknown>): string[] {
|
|
757
|
+
const dimensionValues = objectValue(rowContext, 'dimension_values');
|
|
758
|
+
if (!isRecord(dimensionValues)) return [];
|
|
759
|
+
const labels = Object.values(dimensionValues).flatMap((value) => {
|
|
760
|
+
const dimensionValue = isRecord(value) ? value : {};
|
|
761
|
+
return [
|
|
762
|
+
metricContextLabel(dimensionValue.display_value),
|
|
763
|
+
metricContextLabel(dimensionValue.raw_value),
|
|
764
|
+
metricContextLabel(metricContextStorageRawValue(dimensionValue.storage_value)),
|
|
765
|
+
];
|
|
766
|
+
}).filter(Boolean);
|
|
767
|
+
return Array.from(new Set(labels));
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Checks whether a row-context label can identify the rendered category.
|
|
772
|
+
* @param rowContext - Runtime metric row context.
|
|
773
|
+
* @param categoryLabel - Rendered category label.
|
|
774
|
+
* @param mode - Matching mode.
|
|
775
|
+
* @returns True when the row context belongs to the category label.
|
|
776
|
+
*/
|
|
777
|
+
function metricRowContextMatchesCategoryLabel(
|
|
778
|
+
rowContext: Record<string, unknown>,
|
|
779
|
+
categoryLabel: string,
|
|
780
|
+
mode: 'exact' | 'disambiguated',
|
|
781
|
+
): boolean {
|
|
782
|
+
const labels = metricRowContextLabels(rowContext);
|
|
783
|
+
if (mode === 'exact') return labels.includes(categoryLabel);
|
|
784
|
+
return labels.some((label) => label.startsWith(`${categoryLabel}+`));
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Reads category labels from a category axis.
|
|
789
|
+
* @param axis - ECharts axis option.
|
|
790
|
+
* @returns Axis category labels.
|
|
791
|
+
*/
|
|
792
|
+
function categoryLabelsFromAxis(axis: unknown): string[] {
|
|
793
|
+
const axes = Array.isArray(axis) ? axis : [axis];
|
|
794
|
+
for (const item of axes) {
|
|
795
|
+
if (!isRecord(item) || item.type !== 'category' || !Array.isArray(item.data)) continue;
|
|
796
|
+
const labels = item.data.map(metricContextLabel);
|
|
797
|
+
if (labels.some(Boolean)) return labels;
|
|
798
|
+
}
|
|
799
|
+
return [];
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Reads category labels already present in the normalized runtime option.
|
|
804
|
+
* @param option - Normalized ECharts option.
|
|
805
|
+
* @returns Category labels aligned with scalar series data.
|
|
806
|
+
*/
|
|
807
|
+
function runtimeOptionCategoryLabels(option: EChartsOption): string[] {
|
|
808
|
+
return [
|
|
809
|
+
categoryLabelsFromAxis(objectValue(option, 'xAxis')),
|
|
810
|
+
categoryLabelsFromAxis(objectValue(option, 'yAxis')),
|
|
811
|
+
categoryLabelsFromAxis(objectValue(option, 'angleAxis')),
|
|
812
|
+
].find((labels) => labels.length > 0) ?? [];
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Resolves the rendered category label for one ECharts data item.
|
|
817
|
+
* @param value - Original ECharts series data item.
|
|
818
|
+
* @param index - Series data index.
|
|
819
|
+
* @param categoryLabels - Axis category labels aligned with scalar data.
|
|
820
|
+
* @returns Comparable category label.
|
|
821
|
+
*/
|
|
822
|
+
function runtimeDataItemCategoryLabel(value: unknown, index: number, categoryLabels: string[]): string {
|
|
823
|
+
if (isRecord(value)) {
|
|
824
|
+
const name = metricContextLabel(value.name);
|
|
825
|
+
if (name) return name;
|
|
826
|
+
const itemValue = value.value;
|
|
827
|
+
if (Array.isArray(itemValue)) return metricContextLabel(itemValue[0]);
|
|
828
|
+
return categoryLabels[index] ?? '';
|
|
829
|
+
}
|
|
830
|
+
if (Array.isArray(value)) return metricContextLabel(value[0]);
|
|
831
|
+
return categoryLabels[index] ?? '';
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Finds a unique row context for the clicked/rendered category label.
|
|
836
|
+
* @param rowContexts - Runtime metric row contexts.
|
|
837
|
+
* @param categoryLabel - Rendered category label.
|
|
838
|
+
* @returns Matching row context, or undefined when matching is ambiguous.
|
|
839
|
+
*/
|
|
840
|
+
function metricRowContextByCategoryLabel(
|
|
841
|
+
rowContexts: Record<string, unknown>[],
|
|
842
|
+
categoryLabel: string,
|
|
843
|
+
): Record<string, unknown> | undefined {
|
|
844
|
+
if (!categoryLabel) return undefined;
|
|
845
|
+
const exactMatched = rowContexts.filter((rowContext) => metricRowContextMatchesCategoryLabel(rowContext, categoryLabel, 'exact'));
|
|
846
|
+
const disambiguatedMatched = rowContexts.filter((rowContext) => metricRowContextMatchesCategoryLabel(rowContext, categoryLabel, 'disambiguated'));
|
|
847
|
+
if (exactMatched.length === 1 && disambiguatedMatched.length === 0) return exactMatched[0];
|
|
848
|
+
if (exactMatched.length === 0 && disambiguatedMatched.length === 1) return disambiguatedMatched[0];
|
|
849
|
+
return undefined;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Attaches one row context to an ECharts data item without changing its displayed value.
|
|
854
|
+
* @param value - Original ECharts series data item.
|
|
855
|
+
* @param rowContext - Metric row context for the same rendered item.
|
|
856
|
+
* @returns Series data item carrying item-level detail identity.
|
|
857
|
+
*/
|
|
858
|
+
function dataItemWithRuntimeMetricRowContext(value: unknown, rowContext: Record<string, unknown> | undefined): unknown {
|
|
859
|
+
if (!rowContext && !isRecord(value)) return value;
|
|
860
|
+
if (!rowContext && isRecord(value)) {
|
|
861
|
+
const { [WORKBENCH_METRIC_ROW_CONTEXT_KEY]: _staleContext, ...rest } = value;
|
|
862
|
+
return rest;
|
|
863
|
+
}
|
|
864
|
+
if (isRecord(value)) return { ...value, [WORKBENCH_METRIC_ROW_CONTEXT_KEY]: rowContext };
|
|
865
|
+
return { value, [WORKBENCH_METRIC_ROW_CONTEXT_KEY]: rowContext };
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Preserves metric detail identity on runtime ECharts option data items.
|
|
870
|
+
* @param option - Normalized ECharts option.
|
|
871
|
+
* @param data - Current renderer data.
|
|
872
|
+
* @returns ECharts option whose clickable data items include row contexts.
|
|
873
|
+
*/
|
|
874
|
+
function withRuntimeMetricRowContexts(option: EChartsOption, data: DisplayBlockData): EChartsOption {
|
|
875
|
+
const rowContexts = runtimeMetricRowContexts(data);
|
|
876
|
+
if (rowContexts.length === 0) return option;
|
|
877
|
+
const series = objectValue(option, 'series');
|
|
878
|
+
const categoryLabels = runtimeOptionCategoryLabels(option);
|
|
879
|
+
const attachSeries = (value: unknown): unknown => {
|
|
880
|
+
if (!isRecord(value) || !Array.isArray(value.data)) return value;
|
|
881
|
+
const labels = value.data.map((item, index) => runtimeDataItemCategoryLabel(item, index, categoryLabels));
|
|
882
|
+
const labelCounts = labels.reduce((counts, label) => counts.set(label, (counts.get(label) ?? 0) + 1), new Map<string, number>());
|
|
883
|
+
return {
|
|
884
|
+
...value,
|
|
885
|
+
data: value.data.map((item, index) => dataItemWithRuntimeMetricRowContext(
|
|
886
|
+
item,
|
|
887
|
+
labelCounts.get(labels[index]) === 1 ? metricRowContextByCategoryLabel(rowContexts, labels[index]) : undefined,
|
|
888
|
+
)),
|
|
889
|
+
};
|
|
890
|
+
};
|
|
891
|
+
if (!Array.isArray(series) && !isRecord(series)) return option;
|
|
892
|
+
return {
|
|
893
|
+
...option,
|
|
894
|
+
series: Array.isArray(series) ? series.map(attachSeries) : attachSeries(series),
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function normalizeRuntimeEchartsOption(option: EChartsOption, data: DisplayBlockData): EChartsOption {
|
|
899
|
+
return normalizeSharedWorkbenchChartDisplayDefaults(withRuntimeMetricRowContexts(removeRuntimeEchartsChrome(
|
|
900
|
+
normalizeEchartsOptionPieLegend(
|
|
901
|
+
sanitizeCoordinateFreeRuntimeOption(
|
|
902
|
+
sanitizePolarRuntimeOption(
|
|
903
|
+
recoverMissingCartesianCategoryAxis(option, data),
|
|
904
|
+
),
|
|
905
|
+
),
|
|
906
|
+
),
|
|
907
|
+
), data));
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function optionUsesEchartsGl(option: EChartsOption | null) {
|
|
911
|
+
if (!option) return false;
|
|
912
|
+
if (objectValue(option, 'globe')) return true;
|
|
913
|
+
const series = objectValue(option, 'series');
|
|
914
|
+
const normalizedSeries = Array.isArray(series) ? series : series ? [series] : [];
|
|
915
|
+
return normalizedSeries.some((item) => GL_SERIES_TYPES.has(String(objectValue(item, 'type'))));
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function dataRequiresEchartsGl(data: DisplayBlockData, option: EChartsOption | null) {
|
|
919
|
+
const requires = Array.isArray(objectValue(data, 'requires')) ? objectValue(data, 'requires') as unknown[] : [];
|
|
920
|
+
const engine = String(objectValue(data, 'engine') || '');
|
|
921
|
+
return engine === 'echarts-gl'
|
|
922
|
+
|| requires.some((item) => GL_REQUIREMENTS.has(String(item)))
|
|
923
|
+
|| (data.shape === 'echartsScript' && GL_SCRIPT_PATTERN.test(data.script))
|
|
924
|
+
|| optionUsesEchartsGl(option);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
export function chartTheme(data: DisplayBlockData, option: EChartsOption | null) {
|
|
928
|
+
const explicitTheme = objectValue(data, 'theme');
|
|
929
|
+
if (typeof explicitTheme === 'string' && explicitTheme.trim()) return explicitTheme.trim();
|
|
930
|
+
return dataRequiresEchartsGl(data, option) ? 'dark' : undefined;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
async function ensureEchartsGlLoaded() {
|
|
934
|
+
if (!echartsGlLoadPromise) {
|
|
935
|
+
echartsGlLoadPromise = import('echarts-gl').then(() => undefined);
|
|
936
|
+
}
|
|
937
|
+
await echartsGlLoadPromise;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
function finiteValues(values: number[], fallback = [0, 1]) {
|
|
941
|
+
const safe = values.filter(Number.isFinite);
|
|
942
|
+
return safe.length ? safe : fallback;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Builds common ECharts option defaults.
|
|
947
|
+
* @param colors - Optional generated palette colors.
|
|
948
|
+
* @returns Base ECharts option.
|
|
949
|
+
*/
|
|
950
|
+
function baseOption(colors?: string[]): EChartsOption {
|
|
951
|
+
return {
|
|
952
|
+
color: colors?.length ? colors : CHART_COLORS,
|
|
953
|
+
animationDuration: 500,
|
|
954
|
+
grid: { left: 42, right: 24, top: 28, bottom: 38, containLabel: true },
|
|
955
|
+
tooltip: { trigger: 'item', confine: true },
|
|
956
|
+
textStyle: { color: '#475569', fontFamily: 'Inter, system-ui, sans-serif' },
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Reads a non-empty string color array.
|
|
962
|
+
* @param value - Candidate palette value.
|
|
963
|
+
* @returns Palette colors.
|
|
964
|
+
*/
|
|
965
|
+
function stringPalette(value: unknown): string[] | undefined {
|
|
966
|
+
if (!Array.isArray(value)) return undefined;
|
|
967
|
+
const colors = value
|
|
968
|
+
.map((item) => typeof item === 'string' ? item.trim() : '')
|
|
969
|
+
.filter(Boolean);
|
|
970
|
+
return colors.length > 0 ? colors : undefined;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Reads generated chart colors from renderer data.
|
|
975
|
+
* @param data - Workbench renderer data.
|
|
976
|
+
* @returns Generated palette colors.
|
|
977
|
+
*/
|
|
978
|
+
function paletteColorsFromData(data: unknown): string[] | undefined {
|
|
979
|
+
const directColors = stringPalette(objectValue(data, 'color'));
|
|
980
|
+
if (directColors) return directColors;
|
|
981
|
+
const palette = objectValue(data, 'palette');
|
|
982
|
+
const paletteColors = stringPalette(objectValue(palette, 'colors'));
|
|
983
|
+
return paletteColors ?? stringPalette(palette);
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Reads a generated color from one pie slice.
|
|
988
|
+
* @param slice - Pie slice renderer data.
|
|
989
|
+
* @returns Slice color.
|
|
990
|
+
*/
|
|
991
|
+
function sliceColor(slice: unknown): string | undefined {
|
|
992
|
+
const color = objectValue(slice, 'color');
|
|
993
|
+
return typeof color === 'string' && color.trim() ? color.trim() : undefined;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Reads generated colors from pie slices.
|
|
998
|
+
* @param data - Pie renderer data.
|
|
999
|
+
* @returns Slice-level palette colors.
|
|
1000
|
+
*/
|
|
1001
|
+
function pieSliceColors(data: PieSlicesData): string[] | undefined {
|
|
1002
|
+
const colors = data.slices.map((slice) => sliceColor(slice)).filter((color): color is string => Boolean(color));
|
|
1003
|
+
return colors.length > 0 ? colors : undefined;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
function fallbackSeriesType(rendererKey: string): 'bar' | 'line' {
|
|
1007
|
+
return /bar|column/i.test(rendererKey) && !/line|area/i.test(rendererKey) ? 'bar' : 'line';
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
function seriesOption(data: MultiSeriesData, rendererKey = ''): EChartsOption {
|
|
1011
|
+
assertArray(data.categories, 'categories');
|
|
1012
|
+
assertArray(data.series, 'series');
|
|
1013
|
+
const stacked = data.series.some((item) => item.name.includes('上期')) || data.narrative?.includes('堆叠');
|
|
1014
|
+
const layout = buildCartesianResponsiveLayout(data.categories, data.series.length);
|
|
1015
|
+
return {
|
|
1016
|
+
...baseOption(paletteColorsFromData(data)),
|
|
1017
|
+
grid: layout.grid,
|
|
1018
|
+
legend: layout.legend,
|
|
1019
|
+
xAxis: {
|
|
1020
|
+
type: 'category',
|
|
1021
|
+
data: data.categories,
|
|
1022
|
+
axisLine: { lineStyle: { color: '#dbe4f0' } },
|
|
1023
|
+
axisTick: { show: false },
|
|
1024
|
+
...layout.xAxis,
|
|
1025
|
+
},
|
|
1026
|
+
yAxis: { type: 'value', axisLine: { show: false }, splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1027
|
+
tooltip: { trigger: 'axis', confine: true },
|
|
1028
|
+
series: data.series.map((item) => ({
|
|
1029
|
+
name: item.name,
|
|
1030
|
+
type: item.type || fallbackSeriesType(rendererKey),
|
|
1031
|
+
colorBy: item.colorBy,
|
|
1032
|
+
itemStyle: item.itemStyle,
|
|
1033
|
+
smooth: item.type === 'line',
|
|
1034
|
+
stack: stacked && item.type === 'bar' ? 'total' : undefined,
|
|
1035
|
+
areaStyle: data.unit === '累计指数' && item.type === 'line' ? { opacity: 0.18 } : undefined,
|
|
1036
|
+
data: item.data,
|
|
1037
|
+
barMaxWidth: 34,
|
|
1038
|
+
symbolSize: 7,
|
|
1039
|
+
})),
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
function waterfallOption(data: WaterfallStepsData): EChartsOption {
|
|
1044
|
+
assertArray(data.steps, 'steps');
|
|
1045
|
+
let running = 0;
|
|
1046
|
+
const transparent: number[] = [];
|
|
1047
|
+
const values = data.steps.map((step) => {
|
|
1048
|
+
const raw = step.value ?? step.delta ?? 0;
|
|
1049
|
+
const start = step.delta ? running : 0;
|
|
1050
|
+
transparent.push(Math.max(0, start));
|
|
1051
|
+
running = step.value ?? running + raw;
|
|
1052
|
+
return Math.abs(raw);
|
|
1053
|
+
});
|
|
1054
|
+
return {
|
|
1055
|
+
...baseOption(),
|
|
1056
|
+
xAxis: { type: 'category', data: data.steps.map((step) => step.label), axisTick: { show: false } },
|
|
1057
|
+
yAxis: { type: 'value', splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1058
|
+
tooltip: { trigger: 'axis', confine: true },
|
|
1059
|
+
series: [
|
|
1060
|
+
{ type: 'bar', stack: 'total', itemStyle: { color: 'transparent' }, emphasis: { disabled: true }, data: transparent },
|
|
1061
|
+
{ name: data.unit, type: 'bar', stack: 'total', barMaxWidth: 42, data: values },
|
|
1062
|
+
],
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
function heatmapOption(data: HeatmapMatrixData): EChartsOption {
|
|
1067
|
+
assertArray(data.rows, 'rows');
|
|
1068
|
+
assertArray(data.columns, 'columns');
|
|
1069
|
+
assertArray(data.values, 'values');
|
|
1070
|
+
const values = data.rows.flatMap((row, rowIndex) =>
|
|
1071
|
+
data.columns.map((_column, columnIndex) => [columnIndex, rowIndex, data.values[rowIndex]?.[columnIndex] ?? 0, row]),
|
|
1072
|
+
);
|
|
1073
|
+
const flat = finiteValues(data.values.flat());
|
|
1074
|
+
return {
|
|
1075
|
+
...baseOption(),
|
|
1076
|
+
grid: { left: 80, right: 24, top: 22, bottom: 34 },
|
|
1077
|
+
xAxis: { type: 'category', data: data.columns, splitArea: { show: true } },
|
|
1078
|
+
yAxis: { type: 'category', data: data.rows, splitArea: { show: true } },
|
|
1079
|
+
visualMap: { min: Math.min(...flat), max: Math.max(...flat), calculable: false, orient: 'horizontal', left: 'center', bottom: 0, inRange: { color: ['#dbeafe', '#1f4fd4'] } },
|
|
1080
|
+
series: [{ type: 'heatmap', data: values, label: { show: true } }],
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function pieOption(data: PieSlicesData): EChartsOption {
|
|
1085
|
+
assertArray(data.slices, 'slices');
|
|
1086
|
+
const layout = buildPieResponsiveLayout(data.slices);
|
|
1087
|
+
const colors = pieSliceColors(data) ?? paletteColorsFromData(data);
|
|
1088
|
+
const isDonut = Boolean(data.innerRadius);
|
|
1089
|
+
return {
|
|
1090
|
+
...baseOption(colors),
|
|
1091
|
+
legend: layout.legend,
|
|
1092
|
+
series: [{
|
|
1093
|
+
type: 'pie',
|
|
1094
|
+
radius: data.innerRadius ? [`${data.innerRadius * 100}%`, '72%'] : ['0%', '72%'],
|
|
1095
|
+
center: layout.series.center,
|
|
1096
|
+
avoidLabelOverlap: true,
|
|
1097
|
+
label: isDonut ? { show: false } : layout.series.label,
|
|
1098
|
+
labelLine: isDonut ? { show: false } : layout.series.labelLine,
|
|
1099
|
+
labelLayout: layout.series.labelLayout,
|
|
1100
|
+
minShowLabelAngle: layout.series.minShowLabelAngle,
|
|
1101
|
+
emphasis: isDonut
|
|
1102
|
+
? {
|
|
1103
|
+
label: {
|
|
1104
|
+
show: true,
|
|
1105
|
+
position: 'center',
|
|
1106
|
+
fontSize: 16,
|
|
1107
|
+
fontWeight: 600,
|
|
1108
|
+
},
|
|
1109
|
+
}
|
|
1110
|
+
: undefined,
|
|
1111
|
+
data: data.slices.map((item) => ({
|
|
1112
|
+
name: item.label,
|
|
1113
|
+
value: item.value,
|
|
1114
|
+
...(sliceColor(item) ? { itemStyle: { color: sliceColor(item) } } : {}),
|
|
1115
|
+
})),
|
|
1116
|
+
}],
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
function radarOption(data: RadarMetricsData): EChartsOption {
|
|
1121
|
+
assertArray(data.axes, 'axes');
|
|
1122
|
+
return {
|
|
1123
|
+
...baseOption(),
|
|
1124
|
+
radar: { radius: '68%', indicator: data.axes.map((axis) => ({ name: axis.label, max: data.max })), splitArea: { areaStyle: { color: ['#f8fafc', '#eef2ff'] } } },
|
|
1125
|
+
series: [{ type: 'radar', areaStyle: { opacity: 0.18 }, data: [{ name: '评分', value: data.axes.map((axis) => axis.value) }] }],
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
function scatterOption(data: ScatterPointsData): EChartsOption {
|
|
1130
|
+
assertArray(data.points, 'points');
|
|
1131
|
+
return {
|
|
1132
|
+
...baseOption(),
|
|
1133
|
+
xAxis: { type: 'value', name: data.xLabel, splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1134
|
+
yAxis: { type: 'value', name: data.yLabel, splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1135
|
+
tooltip: {
|
|
1136
|
+
formatter: (params: unknown) => {
|
|
1137
|
+
const item = params as { data?: [number, number, number, string] };
|
|
1138
|
+
return `${item.data?.[3] || ''}<br/>${data.xLabel}: ${item.data?.[0]}<br/>${data.yLabel}: ${item.data?.[1]}${data.sizeLabel ? `<br/>${data.sizeLabel}: ${item.data?.[2]}` : ''}`;
|
|
1139
|
+
},
|
|
1140
|
+
},
|
|
1141
|
+
series: [{
|
|
1142
|
+
type: 'scatter',
|
|
1143
|
+
data: data.points.map((point) => [point.x, point.y, point.size || 12, point.label]),
|
|
1144
|
+
symbolSize: (value: unknown) => {
|
|
1145
|
+
const tuple = value as [number, number, number];
|
|
1146
|
+
return data.sizeLabel ? Math.max(12, tuple[2]) : 14;
|
|
1147
|
+
},
|
|
1148
|
+
}],
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
function funnelOption(data: FunnelStagesData): EChartsOption {
|
|
1153
|
+
assertArray(data.stages, 'stages');
|
|
1154
|
+
return {
|
|
1155
|
+
...baseOption(),
|
|
1156
|
+
legend: { bottom: 0 },
|
|
1157
|
+
series: [{ type: 'funnel', left: '10%', top: 18, bottom: 28, width: '80%', minSize: '28%', maxSize: '92%', sort: 'descending', gap: 4, label: { formatter: '{b}: {c}' }, data: data.stages.map((stage) => ({ name: stage.label, value: stage.value })) }],
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function gaugeOption(data: GaugeMetricData): EChartsOption {
|
|
1162
|
+
return {
|
|
1163
|
+
...baseOption(),
|
|
1164
|
+
series: [{ type: 'gauge', min: 0, max: data.max, progress: { show: true, width: 16 }, axisLine: { lineStyle: { width: 16 } }, pointer: { width: 4 }, detail: { formatter: `{value}${data.unit || ''}`, fontSize: 28, color: '#0f172a' }, data: [{ value: data.value, name: data.label }] }],
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
function mapOption(data: MapRegionsData): EChartsOption {
|
|
1169
|
+
assertArray(data.regions, 'regions');
|
|
1170
|
+
ensureMapRegistered();
|
|
1171
|
+
const values = finiteValues(data.regions.map((region) => region.value));
|
|
1172
|
+
return {
|
|
1173
|
+
...baseOption(),
|
|
1174
|
+
visualMap: { min: Math.min(...values), max: Math.max(...values), left: 0, bottom: 0, text: ['高', '低'], inRange: { color: ['#dbeafe', '#93c5fd', '#1f4fd4'] } },
|
|
1175
|
+
series: [{ type: 'map', map: 'workbench-regions', roam: false, label: { show: true, color: '#0f172a' }, data: data.regions.map((region) => ({ name: region.name, value: region.value })) }],
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
function sankeyOption(data: SankeyFlowData): EChartsOption {
|
|
1180
|
+
assertArray(data.nodes, 'nodes');
|
|
1181
|
+
assertArray(data.links, 'links');
|
|
1182
|
+
const labels = new Map(data.nodes.map((node) => [node.id, node.label]));
|
|
1183
|
+
return {
|
|
1184
|
+
...baseOption(),
|
|
1185
|
+
series: [{ type: 'sankey', left: 12, right: 20, top: 14, bottom: 14, nodeAlign: 'justify', data: data.nodes.map((node) => ({ name: node.label })), links: data.links.map((link) => ({ source: labels.get(link.source) || link.source, target: labels.get(link.target) || link.target, value: link.value })), lineStyle: { color: 'gradient', curveness: 0.5 } }],
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
function toTreeOptionNode(node: TreeNodeData): Record<string, unknown> {
|
|
1190
|
+
return { name: node.label, value: node.value, children: node.children?.map((child) => toTreeOptionNode(child)) };
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
function treeOption(data: TreeHierarchyData): EChartsOption {
|
|
1194
|
+
assertRecord(data.root, 'treeHierarchy.root');
|
|
1195
|
+
return {
|
|
1196
|
+
...baseOption(),
|
|
1197
|
+
series: [{ type: 'tree', data: [toTreeOptionNode(data.root)], top: 18, left: 16, bottom: 18, right: 110, symbolSize: 9, orient: 'LR', label: { position: 'left', verticalAlign: 'middle', align: 'right' }, leaves: { label: { position: 'right', verticalAlign: 'middle', align: 'left' } }, expandAndCollapse: false }],
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
function ganttOption(data: GanttTasksData): EChartsOption {
|
|
1202
|
+
assertArray(data.timeline, 'timeline');
|
|
1203
|
+
assertArray(data.tasks, 'tasks');
|
|
1204
|
+
const statusColors: Record<GanttTasksData['tasks'][number]['status'], string> = { done: '#16a34a', running: '#1f4fd4', pending: '#94a3b8', risk: '#dc2626' };
|
|
1205
|
+
return {
|
|
1206
|
+
...baseOption(),
|
|
1207
|
+
grid: { left: 90, right: 28, top: 26, bottom: 34 },
|
|
1208
|
+
xAxis: { type: 'category', data: data.timeline, axisTick: { show: false } },
|
|
1209
|
+
yAxis: { type: 'category', data: data.tasks.map((task) => task.label), axisTick: { show: false } },
|
|
1210
|
+
series: [{
|
|
1211
|
+
type: 'custom',
|
|
1212
|
+
renderItem(_params: unknown, api: unknown) {
|
|
1213
|
+
const typedApi = api as { value: (index: number) => number | string; coord: (value: [number, number]) => [number, number]; size: (value: [number, number]) => [number, number]; style: (style: Record<string, unknown>) => Record<string, unknown> };
|
|
1214
|
+
const categoryIndex = Number(typedApi.value(0));
|
|
1215
|
+
const start = Number(typedApi.value(1));
|
|
1216
|
+
const end = Number(typedApi.value(2));
|
|
1217
|
+
const status = String(typedApi.value(3)) as GanttTasksData['tasks'][number]['status'];
|
|
1218
|
+
const startPoint = typedApi.coord([start, categoryIndex]);
|
|
1219
|
+
const endPoint = typedApi.coord([end, categoryIndex]);
|
|
1220
|
+
const height = typedApi.size([0, 1])[1] * 0.48;
|
|
1221
|
+
return { type: 'rect', shape: { x: startPoint[0], y: startPoint[1] - height / 2, width: Math.max(8, endPoint[0] - startPoint[0]), height, r: 6 }, style: typedApi.style({ fill: statusColors[status] || '#1f4fd4' }) };
|
|
1222
|
+
},
|
|
1223
|
+
encode: { x: [1, 2], y: 0 },
|
|
1224
|
+
data: data.tasks.map((task, index) => [index, task.start, task.end, task.status, task.owner]),
|
|
1225
|
+
}],
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
function candlestickOption(data: CandlestickSeriesData): EChartsOption {
|
|
1230
|
+
assertArray(data.categories, 'categories');
|
|
1231
|
+
assertArray(data.values, 'values');
|
|
1232
|
+
return {
|
|
1233
|
+
...baseOption(),
|
|
1234
|
+
xAxis: { type: 'category', data: data.categories, boundaryGap: true },
|
|
1235
|
+
yAxis: { type: 'value', scale: true, splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1236
|
+
series: [{ type: 'candlestick', data: data.values.map((item) => [item.open, item.close, item.low, item.high]), itemStyle: { color: '#16a34a', color0: '#dc2626', borderColor: '#16a34a', borderColor0: '#dc2626' } }],
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
function boxplotOption(data: BoxplotSeriesData): EChartsOption {
|
|
1241
|
+
assertArray(data.categories, 'categories');
|
|
1242
|
+
assertArray(data.values, 'values');
|
|
1243
|
+
return {
|
|
1244
|
+
...baseOption(),
|
|
1245
|
+
xAxis: { type: 'category', data: data.categories, axisTick: { show: false } },
|
|
1246
|
+
yAxis: { type: 'value', scale: true, splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1247
|
+
tooltip: { trigger: 'item', confine: true },
|
|
1248
|
+
series: [{ type: 'boxplot', data: data.values }],
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
function paretoOption(data: ParetoSeriesData): EChartsOption {
|
|
1253
|
+
assertArray(data.categories, 'categories');
|
|
1254
|
+
assertArray(data.bars, 'bars');
|
|
1255
|
+
assertArray(data.cumulative, 'cumulative');
|
|
1256
|
+
const barName = '需求数';
|
|
1257
|
+
const cumulativeName = '累计占比(%)';
|
|
1258
|
+
return {
|
|
1259
|
+
...baseOption(),
|
|
1260
|
+
legend: { bottom: 0, data: [barName, cumulativeName] },
|
|
1261
|
+
xAxis: { type: 'category', data: data.categories, axisTick: { show: false } },
|
|
1262
|
+
yAxis: [
|
|
1263
|
+
{ type: 'value', name: barName, splitLine: { lineStyle: { color: '#eef2f7' } } },
|
|
1264
|
+
{ type: 'value', name: '累计占比', min: 0, max: 100, axisLabel: { formatter: '{value}%' } },
|
|
1265
|
+
],
|
|
1266
|
+
tooltip: { trigger: 'axis', confine: true, formatter: paretoTooltipFormatter },
|
|
1267
|
+
series: [{ name: barName, type: 'bar', barMaxWidth: 34, data: data.bars }, { name: cumulativeName, type: 'line', yAxisIndex: 1, smooth: true, data: data.cumulative }],
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function paretoTooltipFormatter(params: unknown): string {
|
|
1272
|
+
const items = Array.isArray(params) ? params as Array<Record<string, unknown>> : [];
|
|
1273
|
+
const title = typeof items[0]?.name === 'string' ? items[0].name : '';
|
|
1274
|
+
const dataIndex = typeof items[0]?.dataIndex === 'number' ? items[0].dataIndex : 0;
|
|
1275
|
+
const lines = items.map((item) => {
|
|
1276
|
+
const marker = typeof item.marker === 'string' ? item.marker : '';
|
|
1277
|
+
const name = String(item.seriesName ?? '');
|
|
1278
|
+
const value = typeof item.value === 'number' ? item.value : Number(item.value);
|
|
1279
|
+
if (name.includes('累计占比')) {
|
|
1280
|
+
return `${marker}累计占比:${formatParetoPercent(value)}`;
|
|
1281
|
+
}
|
|
1282
|
+
return `${marker}${name}:${Number.isFinite(value) ? value : ''}`;
|
|
1283
|
+
});
|
|
1284
|
+
return [title, ...lines, `前 ${dataIndex + 1} 项累计占全部的比例`].filter(Boolean).join('<br/>');
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
function formatParetoPercent(value: number): string {
|
|
1288
|
+
if (!Number.isFinite(value)) return '';
|
|
1289
|
+
return `${Number(value.toFixed(2))}%`;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
function networkOption(data: NetworkGraphData): EChartsOption {
|
|
1293
|
+
assertArray(data.nodes, 'nodes');
|
|
1294
|
+
assertArray(data.links, 'links');
|
|
1295
|
+
const categoryNames: string[] = Array.from(new Set(data.nodes.map((node) => node.category || '默认')));
|
|
1296
|
+
const categories = categoryNames.map((name) => ({ name }));
|
|
1297
|
+
return {
|
|
1298
|
+
...baseOption(),
|
|
1299
|
+
tooltip: { trigger: 'item', confine: true },
|
|
1300
|
+
legend: { bottom: 0, data: categories.map((item) => item.name) },
|
|
1301
|
+
series: [{ type: 'graph', layout: 'force', roam: false, draggable: false, categories, force: { repulsion: 160, edgeLength: 88 }, label: { show: true, formatter: '{b}' }, lineStyle: { color: '#94a3b8', opacity: 0.8 }, data: data.nodes.map((node) => ({ id: node.id, name: node.label, value: node.value, category: node.category || '默认', symbolSize: Math.max(24, Math.min(56, node.value || 28)) })), links: data.links.map((link) => ({ source: link.source, target: link.target, value: link.value || 1 })) }],
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
function geoGlobeOption(data: GeoGlobeData): EChartsOption {
|
|
1306
|
+
assertArray(data.arcs, 'arcs');
|
|
1307
|
+
const uniqueLabels: string[] = Array.from(new Set(data.arcs.flatMap((arc) => [arc.from, arc.to])));
|
|
1308
|
+
return {
|
|
1309
|
+
...baseOption(),
|
|
1310
|
+
radar: { radius: '62%', indicator: uniqueLabels.slice(0, 6).map((label) => ({ name: label, max: 100 })), splitArea: { areaStyle: { color: ['#eef2ff', '#f8fafc'] } } },
|
|
1311
|
+
series: [{ type: 'radar', areaStyle: { opacity: 0.2 }, data: [{ name: data.centerLabel, value: uniqueLabels.slice(0, 6).map((label) => data.arcs.find((item) => item.from === label || item.to === label)?.value || 36) }] }],
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
function normalizeRootPath(rootPath = '') {
|
|
1316
|
+
const nextRootPath = rootPath.trim() || DEFAULT_ECHARTS_ROOT_PATH;
|
|
1317
|
+
return nextRootPath.replace(/\/$/, '') === OFFICIAL_ECHARTS_ROOT_PATH
|
|
1318
|
+
? DEFAULT_ECHARTS_ROOT_PATH
|
|
1319
|
+
: nextRootPath;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
function resolveEchartsResourceUrl(url: string, rootPath: string) {
|
|
1323
|
+
const normalizedRootPath = normalizeRootPath(rootPath).replace(/\/$/, '');
|
|
1324
|
+
if (url.startsWith(OFFICIAL_ECHARTS_ROOT_PATH)) return url.replace(OFFICIAL_ECHARTS_ROOT_PATH, DEFAULT_ECHARTS_ROOT_PATH);
|
|
1325
|
+
if (/^(https?:)?\/\//.test(url) || /^(data|blob):/.test(url)) return url;
|
|
1326
|
+
if (url === normalizedRootPath || url.startsWith(`${normalizedRootPath}/`)) return url;
|
|
1327
|
+
if (url.startsWith('/')) return `${normalizedRootPath}${url}`;
|
|
1328
|
+
return `${normalizedRootPath}/${url}`;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
function optionItems(value: unknown) {
|
|
1332
|
+
if (!value) return [];
|
|
1333
|
+
return Array.isArray(value) ? value : [value];
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
function collectMapNamesFromOption(option: EChartsOption | null) {
|
|
1337
|
+
const mapNames = new Set<string>();
|
|
1338
|
+
const collectMapName = (candidate: unknown) => {
|
|
1339
|
+
const mapName = objectValue(candidate, 'map') ?? objectValue(candidate, 'mapType');
|
|
1340
|
+
if (typeof mapName === 'string' && mapName.trim()) mapNames.add(mapName.trim());
|
|
1341
|
+
};
|
|
1342
|
+
optionItems(objectValue(option, 'geo')).forEach(collectMapName);
|
|
1343
|
+
optionItems(objectValue(option, 'geo3D')).forEach(collectMapName);
|
|
1344
|
+
optionItems(objectValue(option, 'series')).forEach((item) => {
|
|
1345
|
+
const type = String(objectValue(item, 'type') || '');
|
|
1346
|
+
if (type === 'map' || type === 'map3D') collectMapName(item);
|
|
1347
|
+
});
|
|
1348
|
+
return Array.from(mapNames);
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
function normalizeRuntimeMapNames(value: unknown): unknown {
|
|
1352
|
+
if (Array.isArray(value)) return value.map((item) => normalizeRuntimeMapNames(item));
|
|
1353
|
+
if (!value || typeof value !== 'object') return value;
|
|
1354
|
+
const result: Record<string, unknown> = {};
|
|
1355
|
+
Object.entries(value as Record<string, unknown>).forEach(([key, item]) => {
|
|
1356
|
+
if ((key === 'geo' || key === 'geo3D') && item && typeof item === 'object') {
|
|
1357
|
+
const normalizedGeo = normalizeRuntimeMapNames(item) as Record<string, unknown> | Record<string, unknown>[];
|
|
1358
|
+
const fillMapName = (geoItem: Record<string, unknown>) => (
|
|
1359
|
+
typeof geoItem.map === 'string' || typeof geoItem.mapType === 'string'
|
|
1360
|
+
? geoItem
|
|
1361
|
+
: { ...geoItem, map: 'workbench-regions' }
|
|
1362
|
+
);
|
|
1363
|
+
result[key] = Array.isArray(normalizedGeo)
|
|
1364
|
+
? normalizedGeo.map((geoItem) => (geoItem && typeof geoItem === 'object' ? fillMapName(geoItem) : geoItem))
|
|
1365
|
+
: fillMapName(normalizedGeo);
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
if ((key === 'map' || key === 'mapType') && typeof item === 'string' && !item.trim()) {
|
|
1369
|
+
result[key] = 'workbench-regions';
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
result[key] = normalizeRuntimeMapNames(item);
|
|
1373
|
+
});
|
|
1374
|
+
return result;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
async function ensureEchartsMapRegistered(mapName: string, rootPath: string | undefined) {
|
|
1378
|
+
if (!mapName || echarts.getMap(mapName)) return;
|
|
1379
|
+
if (mapName === 'workbench-regions') {
|
|
1380
|
+
ensureMapRegistered();
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
const normalizedRootPath = normalizeRootPath(rootPath);
|
|
1384
|
+
const cacheKey = `${normalizedRootPath}:${mapName}`;
|
|
1385
|
+
if (!echartsMapLoadPromises.has(cacheKey)) {
|
|
1386
|
+
const resourceUrl = resolveEchartsResourceUrl(`/data/asset/geo/${encodeURIComponent(mapName)}.json`, normalizedRootPath);
|
|
1387
|
+
echartsMapLoadPromises.set(cacheKey, window.fetch(resourceUrl)
|
|
1388
|
+
.then(async (response) => {
|
|
1389
|
+
if (!response.ok) throw new Error(`ECharts 地图资源加载失败:${response.status} ${resourceUrl}`);
|
|
1390
|
+
const geoJson = await response.json();
|
|
1391
|
+
if (!geoJson || typeof geoJson !== 'object' || !Array.isArray((geoJson as Record<string, unknown>).features)) {
|
|
1392
|
+
throw new Error(`ECharts 地图资源格式错误:${mapName}`);
|
|
1393
|
+
}
|
|
1394
|
+
echarts.registerMap(mapName, geoJson as never);
|
|
1395
|
+
})
|
|
1396
|
+
.catch((error) => {
|
|
1397
|
+
echartsMapLoadPromises.delete(cacheKey);
|
|
1398
|
+
throw error;
|
|
1399
|
+
}));
|
|
1400
|
+
}
|
|
1401
|
+
await echartsMapLoadPromises.get(cacheKey);
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
async function ensureEchartsMapsForOption(option: EChartsOption | null, rootPath?: string) {
|
|
1405
|
+
const mapNames = collectMapNamesFromOption(option);
|
|
1406
|
+
if (!mapNames.length) return;
|
|
1407
|
+
await Promise.all(mapNames.map((mapName) => ensureEchartsMapRegistered(mapName, rootPath)));
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
function createJQueryCompat(rootPath: string, isActive: () => boolean, onError: (error: unknown) => void): JQueryCompat {
|
|
1411
|
+
const request = <T>(
|
|
1412
|
+
url: string,
|
|
1413
|
+
read: (response: Response) => Promise<T>,
|
|
1414
|
+
callback?: (data: T) => void,
|
|
1415
|
+
): JQueryCompatRequest<T> => {
|
|
1416
|
+
const resourceUrl = resolveEchartsResourceUrl(String(url), rootPath);
|
|
1417
|
+
const basePromise = window.fetch(resourceUrl)
|
|
1418
|
+
.then((response) => {
|
|
1419
|
+
if (!response.ok) throw new Error(`ECharts 示例资源加载失败:${response.status} ${resourceUrl}`);
|
|
1420
|
+
return read(response);
|
|
1421
|
+
});
|
|
1422
|
+
const handledPromise = basePromise
|
|
1423
|
+
.then((data) => {
|
|
1424
|
+
if (isActive()) callback?.(data);
|
|
1425
|
+
return data;
|
|
1426
|
+
})
|
|
1427
|
+
.catch((error) => {
|
|
1428
|
+
if (isActive()) onError(error);
|
|
1429
|
+
return undefined;
|
|
1430
|
+
}) as JQueryCompatRequest<T>;
|
|
1431
|
+
handledPromise.done = (doneCallback) => {
|
|
1432
|
+
void handledPromise.then((data) => {
|
|
1433
|
+
if (data !== undefined && isActive()) doneCallback(data);
|
|
1434
|
+
});
|
|
1435
|
+
return handledPromise;
|
|
1436
|
+
};
|
|
1437
|
+
handledPromise.fail = (failCallback) => {
|
|
1438
|
+
void basePromise.catch((error) => {
|
|
1439
|
+
if (isActive()) failCallback(error);
|
|
1440
|
+
});
|
|
1441
|
+
return handledPromise;
|
|
1442
|
+
};
|
|
1443
|
+
return handledPromise;
|
|
1444
|
+
};
|
|
1445
|
+
return {
|
|
1446
|
+
get: (url, callback) => request(
|
|
1447
|
+
url,
|
|
1448
|
+
async (response) => {
|
|
1449
|
+
const contentType = response.headers.get('content-type') || '';
|
|
1450
|
+
if (contentType.includes('json') || /\.json(?:$|\?)/.test(url)) return response.json();
|
|
1451
|
+
return response.text();
|
|
1452
|
+
},
|
|
1453
|
+
callback,
|
|
1454
|
+
),
|
|
1455
|
+
getJSON: (url, callback) => request(url, (response) => response.json(), callback),
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
function createScopedChart(chart: ECharts, rootPath: string | undefined, isActive: () => boolean, onError: (error: unknown) => void): ECharts {
|
|
1460
|
+
return new Proxy(chart, {
|
|
1461
|
+
get(target, property, receiver) {
|
|
1462
|
+
const value = Reflect.get(target, property, receiver);
|
|
1463
|
+
if (typeof value !== 'function') return value;
|
|
1464
|
+
return (...args: unknown[]) => {
|
|
1465
|
+
if (!isActive()) return undefined;
|
|
1466
|
+
if (property === 'setOption') {
|
|
1467
|
+
const runtimeArgs = [
|
|
1468
|
+
normalizeSharedWorkbenchChartDisplayDefaults(removeRuntimeEchartsChrome(args[0] as EChartsOption)),
|
|
1469
|
+
...args.slice(1),
|
|
1470
|
+
];
|
|
1471
|
+
void ensureEchartsMapsForOption(runtimeArgs[0] as EChartsOption, rootPath)
|
|
1472
|
+
.then(() => {
|
|
1473
|
+
if (isActive()) {
|
|
1474
|
+
Reflect.apply(value, target, runtimeArgs);
|
|
1475
|
+
bindWorkbenchEChartsRuntimeInteractions(target, runtimeArgs[0] as EChartsOption);
|
|
1476
|
+
}
|
|
1477
|
+
})
|
|
1478
|
+
.catch((error) => {
|
|
1479
|
+
if (isActive()) onError(error);
|
|
1480
|
+
});
|
|
1481
|
+
return undefined;
|
|
1482
|
+
}
|
|
1483
|
+
return Reflect.apply(value, target, args);
|
|
1484
|
+
};
|
|
1485
|
+
},
|
|
1486
|
+
}) as ECharts;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
function createNoopChart(): ECharts {
|
|
1490
|
+
return new Proxy({}, {
|
|
1491
|
+
get() {
|
|
1492
|
+
return () => undefined;
|
|
1493
|
+
},
|
|
1494
|
+
}) as ECharts;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
function createNoopJQuery(): JQueryCompat {
|
|
1498
|
+
const request = Promise.resolve(undefined) as JQueryCompatRequest;
|
|
1499
|
+
request.done = () => request;
|
|
1500
|
+
request.fail = () => request;
|
|
1501
|
+
return {
|
|
1502
|
+
get: () => request,
|
|
1503
|
+
getJSON: () => request,
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
function runEchartsScript(script: string, rootPath: string | undefined, myChart: ECharts, jquery: JQueryCompat): EChartsOption | null {
|
|
1508
|
+
const scope = {
|
|
1509
|
+
option: undefined as EChartsOption | undefined,
|
|
1510
|
+
echarts,
|
|
1511
|
+
myChart,
|
|
1512
|
+
$: jquery,
|
|
1513
|
+
app: {} as EchartsScriptApp,
|
|
1514
|
+
ROOT_PATH: normalizeRootPath(rootPath),
|
|
1515
|
+
window,
|
|
1516
|
+
document,
|
|
1517
|
+
fetch: window.fetch.bind(window),
|
|
1518
|
+
Math,
|
|
1519
|
+
Date,
|
|
1520
|
+
Array,
|
|
1521
|
+
Object,
|
|
1522
|
+
Number,
|
|
1523
|
+
String,
|
|
1524
|
+
Boolean,
|
|
1525
|
+
JSON,
|
|
1526
|
+
console,
|
|
1527
|
+
setTimeout: window.setTimeout.bind(window),
|
|
1528
|
+
clearTimeout: window.clearTimeout.bind(window),
|
|
1529
|
+
setInterval: window.setInterval.bind(window),
|
|
1530
|
+
clearInterval: window.clearInterval.bind(window),
|
|
1531
|
+
};
|
|
1532
|
+
const runner = Function(
|
|
1533
|
+
'scope',
|
|
1534
|
+
`
|
|
1535
|
+
"use strict";
|
|
1536
|
+
var option;
|
|
1537
|
+
const echarts = scope.echarts;
|
|
1538
|
+
const myChart = scope.myChart;
|
|
1539
|
+
const $ = scope.$;
|
|
1540
|
+
const app = scope.app;
|
|
1541
|
+
const ROOT_PATH = scope.ROOT_PATH;
|
|
1542
|
+
const window = scope.window;
|
|
1543
|
+
const document = scope.document;
|
|
1544
|
+
const fetch = scope.fetch;
|
|
1545
|
+
const Math = scope.Math;
|
|
1546
|
+
const Date = scope.Date;
|
|
1547
|
+
const Array = scope.Array;
|
|
1548
|
+
const Object = scope.Object;
|
|
1549
|
+
const Number = scope.Number;
|
|
1550
|
+
const String = scope.String;
|
|
1551
|
+
const Boolean = scope.Boolean;
|
|
1552
|
+
const JSON = scope.JSON;
|
|
1553
|
+
const console = scope.console;
|
|
1554
|
+
const setTimeout = scope.setTimeout;
|
|
1555
|
+
const clearTimeout = scope.clearTimeout;
|
|
1556
|
+
const setInterval = scope.setInterval;
|
|
1557
|
+
const clearInterval = scope.clearInterval;
|
|
1558
|
+
${script}
|
|
1559
|
+
return option;
|
|
1560
|
+
`,
|
|
1561
|
+
) as (scope: EchartsScriptScope) => unknown;
|
|
1562
|
+
const option = runner(scope);
|
|
1563
|
+
if (!option) return null;
|
|
1564
|
+
if (typeof option !== 'object' || Array.isArray(option)) throw new Error('ECharts 示例脚本没有生成 option 对象。');
|
|
1565
|
+
const nextOption = option as EChartsOption;
|
|
1566
|
+
if (optionUsesEchartsGl(nextOption) && !objectValue(nextOption, 'backgroundColor')) {
|
|
1567
|
+
return removeRuntimeEchartsChrome({ backgroundColor: '#000', ...nextOption });
|
|
1568
|
+
}
|
|
1569
|
+
return removeRuntimeEchartsChrome(nextOption);
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
export function optionFromWorkbenchData(rendererKey: string, data: DisplayBlockData): EChartsOption | null {
|
|
1573
|
+
assertRecord(data, 'DisplayBlockData');
|
|
1574
|
+
const normalizedRendererKey = normalizeChartRendererKey(rendererKey || '');
|
|
1575
|
+
const option = (() => {
|
|
1576
|
+
if (data.shape === 'echartsOption' && objectValue(data, 'renderContract') === 'materializedPreview') {
|
|
1577
|
+
return normalizeRuntimeEchartsOption(data.option as EChartsOption, data);
|
|
1578
|
+
}
|
|
1579
|
+
if (data.shape === 'echartsOption' && ['pie', 'donut'].includes(String(normalizedRendererKey)) && Array.isArray(objectValue(data, 'slices'))) {
|
|
1580
|
+
return pieOption(data as unknown as PieSlicesData);
|
|
1581
|
+
}
|
|
1582
|
+
if (data.shape === 'echartsOption') return normalizeRuntimeEchartsOption(data.option as EChartsOption, data);
|
|
1583
|
+
if (data.shape === 'echartsScript') {
|
|
1584
|
+
return runEchartsScript(String(data.script), typeof data.rootPath === 'string' ? data.rootPath : undefined, createNoopChart(), createNoopJQuery());
|
|
1585
|
+
}
|
|
1586
|
+
if (data.shape === 'echartsDynamic') {
|
|
1587
|
+
const dataBinding = objectValue(data, 'dataBinding');
|
|
1588
|
+
const fieldMapping = objectValue(dataBinding, 'fieldMapping');
|
|
1589
|
+
return buildDynamicEchartOption(objectValue(data, 'optionTemplate'), {
|
|
1590
|
+
rows: [],
|
|
1591
|
+
fieldMapping: normalizeDynamicEchartFieldMapping({
|
|
1592
|
+
xField: objectValue(dataBinding, 'xField') ?? objectValue(fieldMapping, 'xField'),
|
|
1593
|
+
yFields: objectValue(dataBinding, 'yFields') ?? objectValue(fieldMapping, 'yFields'),
|
|
1594
|
+
}),
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
if (data.shape === 'singleSeries' || data.shape === 'multiSeries') return seriesOption(data, normalizedRendererKey);
|
|
1598
|
+
if (data.shape === 'waterfallSteps') return waterfallOption(data);
|
|
1599
|
+
if (data.shape === 'heatmapMatrix') return heatmapOption(data);
|
|
1600
|
+
if (data.shape === 'pieSlices') return pieOption(data);
|
|
1601
|
+
if (data.shape === 'radarMetrics') return radarOption(data);
|
|
1602
|
+
if (data.shape === 'scatterPoints') return scatterOption(data);
|
|
1603
|
+
if (data.shape === 'funnelStages') return funnelOption(data);
|
|
1604
|
+
if (data.shape === 'gaugeMetric') return gaugeOption(data);
|
|
1605
|
+
if (data.shape === 'mapRegions') return mapOption(data);
|
|
1606
|
+
if (data.shape === 'sankeyFlow') return sankeyOption(data);
|
|
1607
|
+
if (data.shape === 'treeHierarchy') return treeOption(data);
|
|
1608
|
+
if (data.shape === 'ganttTasks') return ganttOption(data);
|
|
1609
|
+
if (data.shape === 'candlestickSeries') return candlestickOption(data);
|
|
1610
|
+
if (data.shape === 'boxplotSeries') return boxplotOption(data);
|
|
1611
|
+
if (data.shape === 'paretoSeries') return paretoOption(data);
|
|
1612
|
+
if (data.shape === 'networkGraph') return networkOption(data);
|
|
1613
|
+
if (data.shape === 'geoGlobe') return geoGlobeOption(data);
|
|
1614
|
+
if (['bar', 'line', 'mixedBarLine', 'area', 'stackedBar'].includes(String(normalizedRendererKey))) return seriesOption(data as MultiSeriesData, normalizedRendererKey);
|
|
1615
|
+
return null;
|
|
1616
|
+
})();
|
|
1617
|
+
return option ? normalizeSharedWorkbenchChartDisplayDefaults(option) : null;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
export async function prepareWorkbenchChartOption(data: DisplayBlockData, option: EChartsOption | null) {
|
|
1621
|
+
if (dataRequiresEchartsGl(data, option)) await ensureEchartsGlLoaded();
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
export function chartNarrative(data: DisplayBlockData) {
|
|
1625
|
+
return 'narrative' in data ? data.narrative : undefined;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
export type WorkbenchEchartClickParams = {
|
|
1629
|
+
componentType?: string;
|
|
1630
|
+
seriesType?: string;
|
|
1631
|
+
seriesName?: string;
|
|
1632
|
+
name?: string | number;
|
|
1633
|
+
value?: unknown;
|
|
1634
|
+
data?: unknown;
|
|
1635
|
+
dataIndex?: number;
|
|
1636
|
+
event?: {
|
|
1637
|
+
clientX?: number;
|
|
1638
|
+
clientY?: number;
|
|
1639
|
+
offsetX?: number;
|
|
1640
|
+
offsetY?: number;
|
|
1641
|
+
};
|
|
1642
|
+
};
|
|
1643
|
+
|
|
1644
|
+
export function useEchart(
|
|
1645
|
+
elementRef: Ref<HTMLElement | null>,
|
|
1646
|
+
optionRef: Ref<EChartsOption | null>,
|
|
1647
|
+
errorRef?: Ref<string>,
|
|
1648
|
+
themeRef?: Ref<string | undefined>,
|
|
1649
|
+
scriptRef?: Ref<EchartsScriptData | null>,
|
|
1650
|
+
onChartClick?: (params: WorkbenchEchartClickParams) => void,
|
|
1651
|
+
) {
|
|
1652
|
+
const chartRef = shallowRef<ECharts | null>(null);
|
|
1653
|
+
const workbenchThemeVersion = shallowRef(0);
|
|
1654
|
+
let resizeObserver: ResizeObserver | null = null;
|
|
1655
|
+
let workbenchThemeObserver: MutationObserver | null = null;
|
|
1656
|
+
let pendingFrame = 0;
|
|
1657
|
+
let retryFrame = 0;
|
|
1658
|
+
let windowResizeBound = false;
|
|
1659
|
+
let mountId = 0;
|
|
1660
|
+
|
|
1661
|
+
/**
|
|
1662
|
+
* 停止监听工作台主题根节点。
|
|
1663
|
+
*/
|
|
1664
|
+
const stopWorkbenchThemeObserver = () => {
|
|
1665
|
+
workbenchThemeObserver?.disconnect();
|
|
1666
|
+
workbenchThemeObserver = null;
|
|
1667
|
+
};
|
|
1668
|
+
|
|
1669
|
+
/**
|
|
1670
|
+
* 开始监听宿主工作台主题切换,确保 CSS 变量变化后重绘图表。
|
|
1671
|
+
* @param element - 当前图表容器。
|
|
1672
|
+
*/
|
|
1673
|
+
const startWorkbenchThemeObserver = (element: HTMLElement | null) => {
|
|
1674
|
+
stopWorkbenchThemeObserver();
|
|
1675
|
+
if (!element || typeof MutationObserver === 'undefined') return;
|
|
1676
|
+
const themeRoot = resolveWorkbenchChartThemeRoot(element);
|
|
1677
|
+
if (!themeRoot) return;
|
|
1678
|
+
workbenchThemeObserver = new MutationObserver(() => {
|
|
1679
|
+
workbenchThemeVersion.value += 1;
|
|
1680
|
+
});
|
|
1681
|
+
workbenchThemeObserver.observe(themeRoot, {
|
|
1682
|
+
attributes: true,
|
|
1683
|
+
attributeFilter: ['data-workbench-style', 'data-dash-theme', 'style', 'class'],
|
|
1684
|
+
});
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
const dispose = () => {
|
|
1688
|
+
mountId += 1;
|
|
1689
|
+
if (pendingFrame) window.cancelAnimationFrame(pendingFrame);
|
|
1690
|
+
if (retryFrame) window.cancelAnimationFrame(retryFrame);
|
|
1691
|
+
pendingFrame = 0;
|
|
1692
|
+
retryFrame = 0;
|
|
1693
|
+
if (windowResizeBound) {
|
|
1694
|
+
window.removeEventListener('resize', resize);
|
|
1695
|
+
windowResizeBound = false;
|
|
1696
|
+
}
|
|
1697
|
+
resizeObserver?.disconnect();
|
|
1698
|
+
resizeObserver = null;
|
|
1699
|
+
chartRef.value?.dispose();
|
|
1700
|
+
chartRef.value = null;
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
const resize = () => {
|
|
1704
|
+
const element = elementRef.value;
|
|
1705
|
+
const chart = chartRef.value;
|
|
1706
|
+
if (!element || !chart) return;
|
|
1707
|
+
const { width, height } = element.getBoundingClientRect();
|
|
1708
|
+
const nextWidth = Math.round(width);
|
|
1709
|
+
const nextHeight = Math.round(height);
|
|
1710
|
+
if (nextWidth <= 0 || nextHeight <= 0) return;
|
|
1711
|
+
if (pendingFrame) window.cancelAnimationFrame(pendingFrame);
|
|
1712
|
+
pendingFrame = window.requestAnimationFrame(() => {
|
|
1713
|
+
pendingFrame = 0;
|
|
1714
|
+
chart.resize({ width: nextWidth, height: nextHeight });
|
|
1715
|
+
});
|
|
1716
|
+
};
|
|
1717
|
+
|
|
1718
|
+
const mount = async () => {
|
|
1719
|
+
await nextTick();
|
|
1720
|
+
const currentMountId = mountId + 1;
|
|
1721
|
+
mountId = currentMountId;
|
|
1722
|
+
const element = elementRef.value;
|
|
1723
|
+
const option = optionRef.value;
|
|
1724
|
+
const scriptData = scriptRef?.value || null;
|
|
1725
|
+
dispose();
|
|
1726
|
+
mountId = currentMountId;
|
|
1727
|
+
if (!element || (!option && !scriptData)) return;
|
|
1728
|
+
const { width, height } = element.getBoundingClientRect();
|
|
1729
|
+
if (width <= 0 || height <= 0) {
|
|
1730
|
+
retryFrame = window.requestAnimationFrame(() => {
|
|
1731
|
+
retryFrame = 0;
|
|
1732
|
+
void mount();
|
|
1733
|
+
});
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
try {
|
|
1737
|
+
const chart = echarts.init(element, themeRef?.value, {
|
|
1738
|
+
renderer: 'canvas',
|
|
1739
|
+
width: Math.round(width),
|
|
1740
|
+
height: Math.round(height),
|
|
1741
|
+
});
|
|
1742
|
+
chartRef.value = chart;
|
|
1743
|
+
if (onChartClick) {
|
|
1744
|
+
chart.on('click', (params) => {
|
|
1745
|
+
if (isWorkbenchHalfDonutPlaceholderData(params.data)) return;
|
|
1746
|
+
const event = (params.event as { event?: MouseEvent; offsetX?: number; offsetY?: number } | undefined);
|
|
1747
|
+
onChartClick({
|
|
1748
|
+
componentType: typeof params.componentType === 'string' ? params.componentType : undefined,
|
|
1749
|
+
seriesType: typeof params.seriesType === 'string' ? params.seriesType : undefined,
|
|
1750
|
+
seriesName: typeof params.seriesName === 'string' ? params.seriesName : undefined,
|
|
1751
|
+
name: typeof params.name === 'string' || typeof params.name === 'number' ? params.name : undefined,
|
|
1752
|
+
value: params.value,
|
|
1753
|
+
data: params.data,
|
|
1754
|
+
dataIndex: typeof params.dataIndex === 'number' ? params.dataIndex : undefined,
|
|
1755
|
+
event: {
|
|
1756
|
+
clientX: event?.event?.clientX,
|
|
1757
|
+
clientY: event?.event?.clientY,
|
|
1758
|
+
offsetX: event?.offsetX,
|
|
1759
|
+
offsetY: event?.offsetY,
|
|
1760
|
+
},
|
|
1761
|
+
});
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1764
|
+
resizeObserver = new ResizeObserver(resize);
|
|
1765
|
+
resizeObserver.observe(element);
|
|
1766
|
+
if (!windowResizeBound) {
|
|
1767
|
+
window.addEventListener('resize', resize);
|
|
1768
|
+
windowResizeBound = true;
|
|
1769
|
+
}
|
|
1770
|
+
const isActive = () => mountId === currentMountId && chartRef.value === chart;
|
|
1771
|
+
if (option) {
|
|
1772
|
+
const themedOption = applyWorkbenchChartThemeToOption(option, readWorkbenchChartThemeTokens(element));
|
|
1773
|
+
const runtimeOption = prepareWorkbenchEChartsRuntimeOption(normalizeRuntimeMapNames(themedOption) as EChartsOption);
|
|
1774
|
+
await ensureEchartsMapsForOption(runtimeOption, scriptData?.rootPath);
|
|
1775
|
+
if (!isActive()) return;
|
|
1776
|
+
chart.setOption(runtimeOption, true);
|
|
1777
|
+
bindWorkbenchEChartsRuntimeInteractions(chart, runtimeOption);
|
|
1778
|
+
}
|
|
1779
|
+
if (scriptData) {
|
|
1780
|
+
const onScriptError = (error: unknown) => {
|
|
1781
|
+
errorRef && (errorRef.value = error instanceof Error ? error.message : 'ECharts 示例执行失败');
|
|
1782
|
+
};
|
|
1783
|
+
const scriptChart = createScopedChart(chart, scriptData.rootPath, isActive, onScriptError);
|
|
1784
|
+
const jquery = createJQueryCompat(scriptData.rootPath || '', isActive, (error) => {
|
|
1785
|
+
errorRef && (errorRef.value = error instanceof Error ? error.message : 'ECharts 示例资源加载失败');
|
|
1786
|
+
});
|
|
1787
|
+
const scriptOption = runEchartsScript(scriptData.script, scriptData.rootPath, scriptChart, jquery);
|
|
1788
|
+
if (scriptOption && isActive()) {
|
|
1789
|
+
const themedScriptOption = applyWorkbenchChartThemeToOption(scriptOption, readWorkbenchChartThemeTokens(element));
|
|
1790
|
+
const runtimeScriptOption = prepareWorkbenchEChartsRuntimeOption(themedScriptOption);
|
|
1791
|
+
await ensureEchartsMapsForOption(runtimeScriptOption, scriptData.rootPath);
|
|
1792
|
+
if (isActive()) {
|
|
1793
|
+
chart.setOption(runtimeScriptOption, true);
|
|
1794
|
+
bindWorkbenchEChartsRuntimeInteractions(chart, runtimeScriptOption);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
resize();
|
|
1799
|
+
errorRef && (errorRef.value = '');
|
|
1800
|
+
} catch (error) {
|
|
1801
|
+
dispose();
|
|
1802
|
+
errorRef && (errorRef.value = error instanceof Error ? error.message : '图表渲染失败');
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1805
|
+
|
|
1806
|
+
watch(elementRef, (element) => {
|
|
1807
|
+
startWorkbenchThemeObserver(element);
|
|
1808
|
+
}, { immediate: true });
|
|
1809
|
+
|
|
1810
|
+
watch([elementRef, optionRef, themeRef || shallowRef(undefined), scriptRef || shallowRef(null), workbenchThemeVersion], () => {
|
|
1811
|
+
void mount();
|
|
1812
|
+
}, { immediate: true });
|
|
1813
|
+
|
|
1814
|
+
onBeforeUnmount(() => {
|
|
1815
|
+
stopWorkbenchThemeObserver();
|
|
1816
|
+
dispose();
|
|
1817
|
+
});
|
|
1818
|
+
|
|
1819
|
+
return { chartRef, resize, dispose };
|
|
1820
|
+
}
|