@gadmin2n/schematics 0.0.72 → 0.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +2 -0
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/job.prisma +62 -0
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +0 -21
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/workflow.prisma +171 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/AgendaJob.ts +60 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +1 -1
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowEventOutbox.ts +62 -0
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeInstance.ts +62 -0
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/WorkflowNodeType.ts +62 -0
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +5 -0
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +5 -4
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +14 -7
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +4 -0
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +49 -3
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflow-node-types.ts +746 -0
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/workflows.ts +786 -0
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.controller.ts +6 -0
  19. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agenda/agenda.service.ts +79 -0
  20. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.spec.ts +20 -0
  21. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.controller.ts +145 -0
  22. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.module.ts +10 -0
  23. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/{canvas/canvas.service.spec.ts → agendaJob/agendaJob.service.spec.ts} +71 -65
  24. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/agendaJob/agendaJob.service.ts +83 -0
  25. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/index.ts +2 -1
  26. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.module.ts +9 -0
  27. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/temporal.service.ts +100 -0
  28. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-execution.dto.ts +19 -0
  29. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.dto.ts +43 -0
  30. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-export.service.ts +317 -0
  31. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.controller.ts +16 -0
  32. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow-node-type.service.ts +13 -0
  33. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.controller.ts +220 -0
  34. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.dto.ts +82 -0
  35. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.module.ts +16 -0
  36. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflow/workflow.service.ts +505 -0
  37. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.spec.ts +22 -0
  38. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.controller.ts +147 -0
  39. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.module.ts +10 -0
  40. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.spec.ts +356 -0
  41. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowEventOutbox/workflowEventOutbox.service.ts +110 -0
  42. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.spec.ts +22 -0
  43. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.controller.ts +216 -0
  44. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.module.ts +10 -0
  45. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.spec.ts +356 -0
  46. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeInstance/workflowNodeInstance.service.ts +168 -0
  47. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.spec.ts +22 -0
  48. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.controller.ts +199 -0
  49. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.module.ts +10 -0
  50. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.spec.ts +348 -0
  51. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/workflowNodeType/workflowNodeType.service.ts +106 -0
  52. package/dist/lib/application/files/gadmin2-game-angle-demo/server/yarn.lock +579 -1082
  53. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/README.md +278 -0
  54. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/config/development-sql.yaml +5 -0
  55. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/docker-compose.yml +25 -0
  56. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/package.json +13 -0
  57. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/sql/create-event-trigger.sql +87 -0
  58. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/.env +7 -0
  59. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/SANDBOX.md +122 -0
  60. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package-lock.json +4285 -0
  61. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/package.json +28 -0
  62. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/code-execute.test.ts +44 -0
  63. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/activities/http-request.test.ts +87 -0
  64. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/helpers.test.ts +225 -0
  65. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/__tests__/node-type-consistency.test.ts +101 -0
  66. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/code-execute.ts +51 -0
  67. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-execute.ts +85 -0
  68. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/db-query.ts +35 -0
  69. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/http-request.ts +54 -0
  70. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/index.ts +6 -0
  71. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/reporting.ts +62 -0
  72. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/activities/send-notification.ts +47 -0
  73. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/config.ts +13 -0
  74. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/condition.ts +101 -0
  75. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/context.ts +58 -0
  76. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/graph.ts +184 -0
  77. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/helpers.ts +133 -0
  78. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/node-types.ts +57 -0
  79. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/dsl/types.ts +77 -0
  80. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/index.ts +36 -0
  81. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/outbox-poller.ts +226 -0
  82. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/src/workflows/dsl-workflow.ts +411 -0
  83. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/tsconfig.json +19 -0
  84. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/vitest.config.ts +8 -0
  85. package/dist/lib/application/files/gadmin2-game-angle-demo/temporal/worker/yarn.lock +1905 -0
  86. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package-lock.json +17555 -0
  87. package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +5 -2
  88. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +1 -0
  89. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +5 -1
  90. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +1 -1
  91. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +63 -0
  92. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +91 -2
  93. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/list.tsx +48 -2
  94. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/show.tsx +43 -2
  95. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +14 -9
  96. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +14 -9
  97. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/index.tsx +309 -56
  98. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agenda/show.tsx +1 -3
  99. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/create.tsx +108 -0
  100. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/edit.tsx +124 -0
  101. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/index.tsx +4 -0
  102. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/list.tsx +245 -0
  103. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/agendaJob/show.tsx +70 -0
  104. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasListPage.tsx +0 -1
  105. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +160 -2
  106. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +120 -148
  107. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CodeFloatWindow.tsx +74 -181
  108. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/LivePreview.tsx +15 -13
  109. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasConfigRegistry.tsx +2 -2
  110. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +338 -3
  111. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasDefaults.ts +18 -17
  112. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/BarChartDataSourceModal.tsx +10 -4
  113. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/LineChartDataSourceModal.tsx +10 -4
  114. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/{ChartViewerConfigModal.tsx → MultiChartConfigModal.tsx} +30 -18
  115. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/MultiChartDataSourceModal.tsx +427 -0
  116. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/NumCardDataSourceModal.tsx +10 -4
  117. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/PromptModal.tsx +6 -14
  118. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/RadarChartDataSourceModal.tsx +10 -4
  119. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/TableDataSourceModal.tsx +10 -4
  120. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/components/canvasModalProps.ts +24 -0
  121. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/demos.ts +45 -63
  122. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/CustomNode.tsx +99 -0
  123. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ExportModal.tsx +87 -0
  124. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/FlowRenderer.tsx +322 -0
  125. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/ImportModal.tsx +175 -0
  126. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodeEditModal.tsx +60 -0
  127. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/NodePropertyPanel.tsx +1150 -0
  128. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/RunWorkflowModal.tsx +101 -0
  129. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/StatusCards.tsx +198 -0
  130. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/components/VersionPanel.tsx +81 -0
  131. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/editor.tsx +566 -0
  132. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/hooks/useWorkflowAgent.ts +224 -0
  133. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/index.tsx +524 -0
  134. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instance-detail.tsx +343 -0
  135. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/instances.tsx +243 -0
  136. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/CreateNodeInstanceModal.tsx +363 -0
  137. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/DynamicConfigForm.tsx +154 -0
  138. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/components/NodeInstanceForm.tsx +176 -0
  139. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/create.tsx +77 -0
  140. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/edit.tsx +112 -0
  141. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/index.tsx +305 -0
  142. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/node-instances/show.tsx +282 -0
  143. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/show.tsx +469 -0
  144. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflow/types.ts +92 -0
  145. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/create.tsx +111 -0
  146. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/edit.tsx +127 -0
  147. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/index.tsx +4 -0
  148. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/list.tsx +254 -0
  149. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/workflowEventOutbox/show.tsx +74 -0
  150. package/dist/lib/application/files/gadmin2-game-angle-demo/web/yarn.lock +1501 -1199
  151. package/package.json +1 -1
  152. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.spec.ts +0 -22
  153. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/BarChart/index.tsx +0 -896
  154. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartSwitcher/index.tsx +0 -219
  155. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/ChartViewer/index.tsx +0 -159
  156. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Filter/index.tsx +0 -192
  157. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/LineChart/index.tsx +0 -1034
  158. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/NumCard.module.css +0 -8
  159. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumCard/index.tsx +0 -509
  160. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/NumLineCard/index.tsx +0 -66
  161. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/PieChart/index.tsx +0 -552
  162. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/RadarChart/index.tsx +0 -263
  163. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Section/index.tsx +0 -35
  164. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/Table/index.tsx +0 -207
  165. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/TreemapChart/index.tsx +0 -382
  166. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/WorldMap/index.tsx +0 -135
  167. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/chart-constants.ts +0 -53
  168. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/InfoIcon.tsx +0 -8
  169. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/icon/index.ts +0 -1
  170. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/config.ts +0 -31
  171. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/nameMap.json +0 -9
  172. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/map/world.geo.json +0 -39349
  173. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/canvas/metric-info-tooltip/index.tsx +0 -19
@@ -1,896 +0,0 @@
1
- import React, { useMemo, useEffect } from 'react';
2
- import { Spin, Empty } from 'antd';
3
- import type * as echarts from 'echarts';
4
- import { useECharts } from '@/hooks/useECharts';
5
- import {
6
- LEGEND_BASE,
7
- GRID_VERTICAL,
8
- GRID_HORIZONTAL,
9
- } from '../chart-constants';
10
-
11
- // ─── Types ────────────────────────────────────────────────────────────────────
12
-
13
- /**
14
- * bar 单系列数据(direction=vertical 时 name=X轴标签,direction=horizontal 时 name=Y轴标签)
15
- * value = 数值
16
- */
17
- export type BarDataSingle = {
18
- name: string;
19
- value: number | null;
20
- /** 额外描述,显示在 tooltip 或 label 括号内 */
21
- extraTxt?: string;
22
- [key: string]: any;
23
- }[];
24
-
25
- /**
26
- * stackBar 多系列数据
27
- * xData = 分类轴标签数组(纵向时为X轴,横向时为Y轴)
28
- * series[].data 与 xData 等长
29
- */
30
- export interface BarDataMulti {
31
- xData: string[];
32
- series: {
33
- name: string;
34
- data: (number | null)[];
35
- /** 可附加 stack、color、itemStyle 等原生 ECharts 字段 */
36
- [key: string]: any;
37
- }[];
38
- }
39
-
40
- /**
41
- * stackBarPercent 百分比堆叠柱状图数据
42
- * series[].data 为百分比值(0–100);originalData 存原始计数,用于 tooltip/label 展示
43
- * xData 格式为 "YYYYMMDD",展示时自动转 "MM/DD"
44
- */
45
- export interface BarDataPercent {
46
- xData: string[];
47
- series: { name: string; data: number[] }[];
48
- allTypes: string[];
49
- originalData: Record<
50
- string,
51
- Array<{ key: string; active_device_cnt: number; [key: string]: any }>
52
- >;
53
- }
54
-
55
- export type BarChartVariant =
56
- | 'bar' // 单系列柱状图
57
- | 'stackBar' // 多系列堆叠柱状图
58
- | 'stackBarPercent'; // 百分比堆叠柱状图(Y 轴 0–100%,label 在 bar 内显示原始计数)
59
-
60
- export type BarChartDirection = 'vertical' | 'horizontal';
61
-
62
- export type BarChartData = BarDataSingle | BarDataMulti | BarDataPercent;
63
-
64
- export interface BarChartProps {
65
- // ── 核心 ──────────────────────────────────────────────────────────────────
66
- /** 图表数据。bar 用 BarDataSingle;stackBar 用 BarDataMulti;stackBarPercent 用 BarDataPercent */
67
- data: BarChartData;
68
- /** 视觉变体 */
69
- variant?: BarChartVariant;
70
- /** 方向:纵向(默认)或横向 */
71
- direction?: BarChartDirection;
72
- /** Y 轴(纵向)或 X 轴(横向)单位,显示在 tooltip 和 label */
73
- unit?: string;
74
-
75
- // ── 布局 ──────────────────────────────────────────────────────────────────
76
- /**
77
- * 图表标题,渲染在图表上方。
78
- * - 字符串:套默认样式(居中、12px、bold、#515151)
79
- * - ReactNode:直接渲染,样式由调用方控制
80
- * height 只指图表区域高度,标题额外占空间。
81
- */
82
- title?: React.ReactNode;
83
- /** 图表容器高度,默认 300 */
84
- height?: number | string;
85
-
86
- // ── 显示控制 ──────────────────────────────────────────────────────────────
87
- /**
88
- * 是否在 bar 顶部(或横向时右侧)显示 label。
89
- * - bar:默认 true(显示数值 + unit)
90
- * - stackBar:默认 true(仅最后一段显示总量)
91
- */
92
- showLabel?: boolean;
93
- /** 是否显示网格线,默认 true */
94
- showGrid?: boolean;
95
- /** 是否显示图例(多系列默认 true,单系列默认 false) */
96
- legendShow?: boolean;
97
-
98
- // ── 配置覆盖 ──────────────────────────────────────────────────────────────
99
- /**
100
- * 透传至 ECharts option 的配置(yAxis、xAxis、grid 等),与基准配置浅合并。
101
- * 支持:yAxis、xAxis、grid、seriesProps(透传到每条 series)、reverseTooltip(tooltip 反向排序)
102
- */
103
- chartProps?: Record<string, any>;
104
- /** 完全自定义 option,与组件生成的 option 浅合并(优先级最高) */
105
- option?: echarts.EChartsCoreOption;
106
-
107
- // ── 交互 ──────────────────────────────────────────────────────────────────
108
- /**
109
- * 图表实例就绪回调,回传 ECharts 实例(销毁时传 null)。
110
- * 用于 chart linking(如 BarChart ↔ PieChart 联动)。
111
- */
112
- onChartReady?: (instance: echarts.ECharts | null) => void;
113
-
114
- // ── 状态 ──────────────────────────────────────────────────────────────────
115
- /** 显示 Spin 加载态 */
116
- loading?: boolean;
117
- /** 强制显示空态。未传时根据数据是否为空自动判断 */
118
- empty?: boolean;
119
-
120
- // ── 样式 / 测试 ──────────────────────────────────────────────────────────
121
- style?: React.CSSProperties;
122
- className?: string;
123
- /** data-testid,必须填写 */
124
- testId: string;
125
- }
126
-
127
- // ─── 共享常量 ─────────────────────────────────────────────────────────────────
128
-
129
- // LEGEND_BASE, GRID_VERTICAL, GRID_HORIZONTAL 来自 ../chart-constants
130
-
131
- // ─── 工具函数 ─────────────────────────────────────────────────────────────────
132
-
133
- function isMulti(data: BarChartData): data is BarDataMulti {
134
- return !Array.isArray(data) && 'xData' in data && !('allTypes' in data);
135
- }
136
-
137
- function isPercent(data: BarChartData): data is BarDataPercent {
138
- return !Array.isArray(data) && 'allTypes' in data;
139
- }
140
-
141
- function isEmpty(data: BarChartData): boolean {
142
- if (Array.isArray(data)) return data.length === 0;
143
- return (data as BarDataMulti).xData?.length === 0;
144
- }
145
-
146
- // 构建 dateMap:每个 x 轴点上各系列值(用于计算堆叠总量)
147
- function buildDateMap(data: BarDataMulti): Record<string, (number | null)[]> {
148
- const { xData, series } = data;
149
- const map: Record<string, (number | null)[]> = {};
150
- for (let xIdx = 0; xIdx < xData.length; xIdx++) {
151
- const key = xData[xIdx];
152
- for (let sIdx = 0; sIdx < series.length; sIdx++) {
153
- const val = series[sIdx].data[xIdx];
154
- map[key] ? map[key].push(val) : (map[key] = [val]);
155
- }
156
- }
157
- return map;
158
- }
159
-
160
- // ─── Variant 配置构建 ─────────────────────────────────────────────────────────
161
-
162
- function buildBarOption(
163
- data: BarDataSingle,
164
- unit: string,
165
- showLabel: boolean,
166
- chartProps: Record<string, any>,
167
- ): echarts.EChartsCoreOption {
168
- const {
169
- yAxis = {},
170
- xAxis = {},
171
- grid = {},
172
- seriesName = '',
173
- seriesProps = {},
174
- } = chartProps;
175
- return {
176
- legend: { ...LEGEND_BASE, data: [seriesName], show: false },
177
- tooltip: {
178
- trigger: 'item' as const,
179
- formatter: (ctx: any) => {
180
- const { marker, value, name } = ctx || {};
181
- const extraTxt =
182
- data.find((item) => item?.name === name)?.extraTxt || '';
183
- return `${marker}${name}: ${value ?? 0} ${unit}${extraTxt ? `\n(${extraTxt})` : ''}`;
184
- },
185
- },
186
- xAxis: {
187
- type: 'category' as const,
188
- axisTick: { show: false },
189
- data: data.map((item) => item?.name),
190
- axisLabel: {
191
- fontSize: 10,
192
- interval: 0,
193
- hideOverlap: true,
194
- margin: 15,
195
- ...xAxis?.axisLabel,
196
- },
197
- ...xAxis,
198
- },
199
- yAxis: {
200
- type: 'value' as const,
201
- axisLabel: {
202
- fontSize: 10,
203
- formatter: (v: number) => `${v}${unit}`,
204
- ...yAxis?.axisLabel,
205
- },
206
- ...yAxis,
207
- },
208
- grid: { ...GRID_VERTICAL, ...grid },
209
- series: [
210
- {
211
- name: seriesName,
212
- type: 'bar' as const,
213
- barMaxWidth: 50,
214
- data: data.map((item) => item?.value),
215
- label: showLabel
216
- ? {
217
- show: true,
218
- position: 'top' as const,
219
- fontSize: 10,
220
- formatter: (ctx: any) => {
221
- const { dataIndex, value, name } = ctx;
222
- const extraTxt =
223
- data.find((item) => item?.name === name)?.extraTxt || '';
224
- if (
225
- (data.length > 8 && dataIndex % 3 !== 0) ||
226
- (data.length > 6 && data.length < 8 && dataIndex % 2 !== 0)
227
- ) {
228
- return '';
229
- }
230
- return `${value ?? ''}${value !== null ? unit : ''}${extraTxt ? `\n(${extraTxt})` : ''}`;
231
- },
232
- }
233
- : { show: false },
234
- ...seriesProps,
235
- },
236
- ],
237
- };
238
- }
239
-
240
- function buildHorizontalBarOption(
241
- data: BarDataSingle,
242
- unit: string,
243
- showLabel: boolean,
244
- chartProps: Record<string, any>,
245
- ): echarts.EChartsCoreOption {
246
- const {
247
- yAxis = {},
248
- xAxis = {},
249
- grid = {},
250
- seriesName = '',
251
- seriesProps = {},
252
- } = chartProps;
253
- return {
254
- legend: { ...LEGEND_BASE, data: [seriesName], show: false },
255
- tooltip: {
256
- trigger: 'item' as const,
257
- formatter: (ctx: any) => {
258
- const { marker, value, name } = ctx || {};
259
- const extraTxt =
260
- data.find((item) => item?.name === name)?.extraTxt || '';
261
- return `${marker}${name}: ${(value ?? 0)?.toLocaleString()} ${unit}${extraTxt ? `\n(${extraTxt})` : ''}`;
262
- },
263
- },
264
- yAxis: {
265
- type: 'category' as const,
266
- axisTick: { show: false },
267
- axisLabel: {
268
- fontSize: 10,
269
- width: 120,
270
- overflow: 'truncate' as const,
271
- ellipsis: '...',
272
- ...yAxis?.axisLabel,
273
- },
274
- data: data.map((item) => item?.name),
275
- ...yAxis,
276
- },
277
- xAxis: {
278
- type: 'value' as const,
279
- axisTick: { show: false },
280
- axisLabel: {
281
- fontSize: 10,
282
- formatter: (v: number) => `${v?.toLocaleString()}${unit}`,
283
- ...xAxis?.axisLabel,
284
- },
285
- ...xAxis,
286
- },
287
- grid: { ...GRID_HORIZONTAL, ...grid },
288
- series: [
289
- {
290
- name: seriesName,
291
- type: 'bar' as const,
292
- barMaxWidth: 30,
293
- data: data.map((item) => ({ ...item })),
294
- label: showLabel
295
- ? {
296
- show: true,
297
- position: 'right' as const,
298
- fontSize: 10,
299
- color: '#666',
300
- formatter: (ctx: any) => {
301
- const { value, name } = ctx;
302
- const extraTxt =
303
- data.find((item) => item?.name === name)?.extraTxt || '';
304
- return `${(value ?? 0)?.toLocaleString()}${value !== null ? ` ${unit}` : ''}${extraTxt ? `\n(${extraTxt})` : ''}`;
305
- },
306
- }
307
- : { show: false },
308
- ...seriesProps,
309
- },
310
- ],
311
- };
312
- }
313
-
314
- function buildStackBarOption(
315
- data: BarDataMulti,
316
- unit: string,
317
- showLabel: boolean,
318
- chartProps: Record<string, any>,
319
- ): echarts.EChartsCoreOption {
320
- const {
321
- yAxis = {},
322
- xAxis = {},
323
- grid = {},
324
- reverseTooltip = false,
325
- seriesProps = {},
326
- } = chartProps;
327
- const { series = [], xData = [] } = data;
328
- const dateMap = buildDateMap(data);
329
-
330
- return {
331
- tooltip: {
332
- trigger: 'axis' as const,
333
- formatter: (arr: any) => {
334
- const xName = arr[0]?.name;
335
- const sortArr = reverseTooltip ? [...arr].reverse() : arr;
336
- const str = sortArr
337
- .map((item: any) => {
338
- const fData = item?.data ?? item?.value;
339
- return fData !== null && fData !== undefined && fData !== 0
340
- ? `<div>${item?.marker} ${item?.seriesName}: ${fData?.toLocaleString()}${unit}</div>`
341
- : '';
342
- })
343
- .join('');
344
- return `<div>${xName}</div>${str}`;
345
- },
346
- },
347
- legend: {
348
- ...LEGEND_BASE,
349
- data: series.map((item: any) => item?.name),
350
- },
351
- grid: { ...GRID_VERTICAL, ...grid },
352
- xAxis: {
353
- type: 'category' as const,
354
- boundaryGap: true,
355
- data: xData,
356
- axisTick: { show: false },
357
- axisLine: { show: false },
358
- axisLabel: {
359
- fontSize: 10,
360
- interval: 0,
361
- hideOverlap: true,
362
- margin: 15,
363
- ...xAxis?.axisLabel,
364
- },
365
- ...xAxis,
366
- },
367
- yAxis: {
368
- type: 'value' as const,
369
- axisLabel: {
370
- fontSize: 10,
371
- formatter: (v: number) => `${v?.toLocaleString()}${unit}`,
372
- ...yAxis?.axisLabel,
373
- },
374
- axisTick: { show: false },
375
- axisLine: { show: false },
376
- splitNumber: 3,
377
- ...yAxis,
378
- },
379
- series: series.map((item: any, sIdx: number) => {
380
- return {
381
- name: item?.name,
382
- type: 'bar' as const,
383
- barMaxWidth: 50,
384
- stack: item?.stack || 'stackKey',
385
- data: item?.data,
386
- label: showLabel
387
- ? {
388
- show: true,
389
- position: 'top' as const,
390
- fontSize: 10,
391
- formatter: (params: any) => {
392
- const { dataIndex, name } = params;
393
- const validLen =
394
- dateMap[name]?.filter((v: any) => v !== null)?.length ?? 0;
395
- // 只在最后一段显示总量
396
- if (sIdx !== validLen - 1) return '';
397
- const total = series.reduce(
398
- (sum: number, s: any) =>
399
- sum + (Number(s.data[dataIndex]) || 0),
400
- 0,
401
- );
402
- return total ? `${total?.toLocaleString()}${unit}` : '';
403
- },
404
- }
405
- : { show: false },
406
- ...seriesProps,
407
- ...item,
408
- // item 字段不覆盖 label(让我们的 label 生效,除非 item 明确传了 label)
409
- ...(item?.label ? { label: item.label } : showLabel ? {} : {}),
410
- };
411
- }),
412
- };
413
- }
414
-
415
- function buildInversionStackBarOption(
416
- data: BarDataMulti,
417
- unit: string,
418
- showLabel: boolean,
419
- chartProps: Record<string, any>,
420
- ): echarts.EChartsCoreOption {
421
- const {
422
- yAxis = {},
423
- xAxis = {},
424
- grid = {},
425
- seriesProps = {},
426
- reverseTooltip = false,
427
- } = chartProps;
428
- const { series = [], xData = [] } = data;
429
- const dateMap = buildDateMap(data);
430
-
431
- return {
432
- tooltip: {
433
- trigger: 'axis' as const,
434
- formatter: (arr: any) => {
435
- const xName = arr[0]?.name;
436
- const sortArr = reverseTooltip ? [...arr].reverse() : arr;
437
- const str = sortArr
438
- .map((item: any) => {
439
- const val = item?.data ?? item?.value;
440
- return val !== null && val !== undefined
441
- ? `<div>${item?.marker} ${item?.seriesName}: ${val?.toLocaleString()}${unit}</div>`
442
- : '';
443
- })
444
- .join('');
445
- return `<div>${xName}</div>${str}`;
446
- },
447
- },
448
- legend: {
449
- ...LEGEND_BASE,
450
- data: series.map((item: any) => item?.name),
451
- },
452
- grid: { ...GRID_HORIZONTAL, ...grid },
453
- yAxis: {
454
- type: 'category' as const,
455
- axisTick: { show: false },
456
- axisLabel: {
457
- fontSize: 10,
458
- interval: 0,
459
- width: 160,
460
- overflow: 'truncate' as const,
461
- ellipsis: '...',
462
- ...yAxis?.axisLabel,
463
- },
464
- data: xData,
465
- ...yAxis,
466
- },
467
- xAxis: {
468
- type: 'value' as const,
469
- minInterval: 1,
470
- axisLabel: {
471
- fontSize: 10,
472
- formatter: (v: number) => `${v}${unit}`,
473
- ...xAxis?.axisLabel,
474
- },
475
- axisLine: { show: false },
476
- splitLine: { show: false },
477
- ...xAxis,
478
- },
479
- series: series.map((item: any, sIdx: number) => {
480
- return {
481
- name: item?.name,
482
- type: 'bar' as const,
483
- barMaxWidth: 50,
484
- stack: item?.stack || 'stackKey',
485
- data: item?.data,
486
- label: showLabel
487
- ? {
488
- show: true,
489
- position: 'right' as const,
490
- fontSize: 12,
491
- color: '#333',
492
- formatter: (params: any) => {
493
- const { dataIndex, name } = params;
494
- const validLen =
495
- dateMap[name]?.filter((v: any) => v !== null)?.length ?? 0;
496
- if (sIdx !== validLen - 1) return '';
497
- const total = series.reduce(
498
- (sum: number, s: any) =>
499
- sum + (Number(s.data[dataIndex]) || 0),
500
- 0,
501
- );
502
- return total ? `${total}${unit}` : '';
503
- },
504
- }
505
- : { show: false },
506
- ...seriesProps,
507
- ...item,
508
- ...(item?.label ? { label: item.label } : showLabel ? {} : {}),
509
- };
510
- }),
511
- };
512
- }
513
-
514
- function buildStackBarPercentOption(
515
- data: BarDataPercent,
516
- unit: string,
517
- chartProps: Record<string, any>,
518
- ): echarts.EChartsCoreOption {
519
- const { grid = {} } = chartProps;
520
- const { xData = [], series = [], allTypes = [], originalData = {} } = data;
521
-
522
- return {
523
- tooltip: {
524
- trigger: 'axis' as const,
525
- formatter: (arr: any) => {
526
- const xName = arr[0]?.name ?? '';
527
- const originData: any[] = originalData[xName] ?? [];
528
- const dateLabel = xName.replace(/^\d{4}(\d{2})(\d{2})$/, '$1/$2');
529
- const str = arr
530
- .map((item: any) => {
531
- const cnt = (
532
- originData.find((o: any) => o.key === item?.seriesName)
533
- ?.active_device_cnt ?? 0
534
- ).toLocaleString();
535
- return `<div style="text-align:left;">${item?.marker} ${item?.seriesName} ${cnt}(${item.value}${unit})</div>`;
536
- })
537
- .join('');
538
- return `<div style="text-align:left;">${dateLabel}</div>${str}`;
539
- },
540
- },
541
- legend: {
542
- ...LEGEND_BASE,
543
- data: allTypes,
544
- },
545
- grid: {
546
- top: 30,
547
- left: 50,
548
- right: 40,
549
- bottom: 60,
550
- containLabel: true,
551
- ...grid,
552
- },
553
- xAxis: {
554
- type: 'category' as const,
555
- data: xData,
556
- axisTick: { show: false },
557
- axisPointer: { type: 'shadow' as const },
558
- axisLabel: {
559
- fontSize: 10,
560
- formatter: (value: string) =>
561
- value.replace(/^\d{4}(\d{2})(\d{2})$/, '$1/$2'),
562
- },
563
- },
564
- yAxis: {
565
- type: 'value' as const,
566
- max: 100,
567
- nameLocation: 'middle' as const,
568
- nameGap: 80,
569
- position: 'left' as const,
570
- axisLabel: {
571
- fontSize: 10,
572
- formatter: '{value}%',
573
- },
574
- },
575
- series: series.map((barItem: any) => ({
576
- name: barItem.name,
577
- type: 'bar' as const,
578
- barMaxWidth: 50,
579
- stack: 'Total',
580
- data: barItem.data,
581
- label: {
582
- show: true,
583
- position: 'inside' as const,
584
- fontSize: 12,
585
- formatter: (params: any) => {
586
- const oData: any[] = originalData[params.name] ?? [];
587
- const tarData = oData.find(
588
- (item: any) => item.key === params.seriesName,
589
- );
590
- return tarData?.active_device_cnt ?? 0;
591
- },
592
- },
593
- })),
594
- };
595
- }
596
-
597
- function buildInversionStackBarPercentOption(
598
- data: BarDataPercent,
599
- unit: string,
600
- chartProps: Record<string, any>,
601
- ): echarts.EChartsCoreOption {
602
- const { grid = {} } = chartProps;
603
- const { xData = [], series = [], allTypes = [], originalData = {} } = data;
604
-
605
- return {
606
- tooltip: {
607
- trigger: 'axis' as const,
608
- formatter: (arr: any) => {
609
- const yName = arr[0]?.name ?? '';
610
- const originData: any[] = originalData[yName] ?? [];
611
- const dateLabel = yName.replace(/^\d{4}(\d{2})(\d{2})$/, '$1/$2');
612
- const str = arr
613
- .map((item: any) => {
614
- const cnt = (
615
- originData.find((o: any) => o.key === item?.seriesName)
616
- ?.active_device_cnt ?? 0
617
- ).toLocaleString();
618
- return `<div style="text-align:left;">${item?.marker} ${item?.seriesName} ${cnt}(${item.value}${unit})</div>`;
619
- })
620
- .join('');
621
- return `<div style="text-align:left;">${dateLabel}</div>${str}`;
622
- },
623
- },
624
- legend: {
625
- ...LEGEND_BASE,
626
- data: allTypes,
627
- },
628
- grid: {
629
- top: 30,
630
- left: 50,
631
- right: 40,
632
- bottom: 60,
633
- containLabel: true,
634
- ...grid,
635
- },
636
- yAxis: {
637
- type: 'category' as const,
638
- data: xData,
639
- axisTick: { show: false },
640
- axisLabel: {
641
- fontSize: 10,
642
- formatter: (value: string) =>
643
- value.replace(/^\d{4}(\d{2})(\d{2})$/, '$1/$2'),
644
- },
645
- },
646
- xAxis: {
647
- type: 'value' as const,
648
- max: 100,
649
- axisLabel: {
650
- fontSize: 10,
651
- formatter: '{value}%',
652
- },
653
- },
654
- series: series.map((barItem: any) => ({
655
- name: barItem.name,
656
- type: 'bar' as const,
657
- barMaxWidth: 50,
658
- stack: 'Total',
659
- data: barItem.data,
660
- label: {
661
- show: true,
662
- position: 'inside' as const,
663
- fontSize: 12,
664
- formatter: (params: any) => {
665
- const oData: any[] = originalData[params.name] ?? [];
666
- const tarData = oData.find(
667
- (item: any) => item.key === params.seriesName,
668
- );
669
- return tarData?.active_device_cnt ?? 0;
670
- },
671
- },
672
- })),
673
- };
674
- }
675
-
676
- // ─── 组件 ─────────────────────────────────────────────────────────────────────
677
-
678
- export const BarChart: React.FC<BarChartProps> = ({
679
- data,
680
- variant = 'bar',
681
- direction = 'vertical',
682
- unit = '',
683
- title,
684
- height = 300,
685
- showLabel: showLabelProp,
686
- showGrid: showGridProp,
687
- legendShow: legendShowProp,
688
- chartProps = {},
689
- option: optionOverride,
690
- onChartReady,
691
- loading = false,
692
- empty,
693
- style,
694
- className,
695
- testId,
696
- }) => {
697
- // 空态判断
698
- const isEmptyData = empty ?? isEmpty(data);
699
-
700
- // showLabel 默认值
701
- const showLabel = showLabelProp ?? true;
702
-
703
- // showGrid 默认值
704
- const showGrid = showGridProp ?? true;
705
-
706
- // 构建 option
707
- const mergedOption = useMemo(() => {
708
- let baseOption: echarts.EChartsCoreOption;
709
-
710
- if (variant === 'bar' && direction === 'horizontal') {
711
- baseOption = buildHorizontalBarOption(
712
- data as BarDataSingle,
713
- unit,
714
- showLabel,
715
- chartProps,
716
- );
717
- } else if (variant === 'stackBar' && direction === 'horizontal') {
718
- baseOption = buildInversionStackBarOption(
719
- data as BarDataMulti,
720
- unit,
721
- showLabel,
722
- chartProps,
723
- );
724
- } else if (variant === 'stackBarPercent' && direction === 'horizontal') {
725
- baseOption = buildInversionStackBarPercentOption(
726
- data as BarDataPercent,
727
- unit,
728
- chartProps,
729
- );
730
- } else if (variant === 'stackBarPercent') {
731
- baseOption = buildStackBarPercentOption(
732
- data as BarDataPercent,
733
- unit,
734
- chartProps,
735
- );
736
- } else if (variant === 'stackBar') {
737
- baseOption = buildStackBarOption(
738
- data as BarDataMulti,
739
- unit,
740
- showLabel,
741
- chartProps,
742
- );
743
- } else {
744
- // variant === 'bar' && direction === 'vertical' (default)
745
- baseOption = buildBarOption(
746
- data as BarDataSingle,
747
- unit,
748
- showLabel,
749
- chartProps,
750
- );
751
- }
752
-
753
- // legendShow 覆盖
754
- if (legendShowProp !== undefined) {
755
- const legend = baseOption.legend as any;
756
- baseOption = {
757
- ...baseOption,
758
- legend: { ...legend, show: legendShowProp },
759
- };
760
- }
761
-
762
- // showGrid 覆盖:隐藏网格线
763
- if (!showGrid) {
764
- const yAxisBase = (baseOption as any).yAxis ?? {};
765
- const xAxisBase = (baseOption as any).xAxis ?? {};
766
- baseOption = {
767
- ...baseOption,
768
- yAxis: {
769
- ...yAxisBase,
770
- splitLine: { ...yAxisBase.splitLine, show: false },
771
- },
772
- xAxis: {
773
- ...xAxisBase,
774
- splitLine: { ...xAxisBase.splitLine, show: false },
775
- },
776
- };
777
- }
778
-
779
- // option 覆盖合并
780
- if (optionOverride) {
781
- return {
782
- ...baseOption,
783
- ...optionOverride,
784
- ...(optionOverride.legend
785
- ? {
786
- legend: {
787
- ...(baseOption.legend as any),
788
- ...(optionOverride.legend as any),
789
- },
790
- }
791
- : {}),
792
- ...(optionOverride.tooltip
793
- ? {
794
- tooltip: {
795
- ...(baseOption.tooltip as any),
796
- ...(optionOverride.tooltip as any),
797
- },
798
- }
799
- : {}),
800
- };
801
- }
802
-
803
- return baseOption;
804
- }, [
805
- data,
806
- variant,
807
- direction,
808
- unit,
809
- showLabel,
810
- showGrid,
811
- legendShowProp,
812
- chartProps,
813
- optionOverride,
814
- ]);
815
-
816
- const { domRef, chartRef } = useECharts({ option: mergedOption });
817
-
818
- // onChartReady 回调
819
- useEffect(() => {
820
- onChartReady?.(chartRef.current);
821
- return () => {
822
- onChartReady?.(null);
823
- };
824
- }, [chartRef.current, onChartReady]);
825
-
826
- const titleNode = title ? (
827
- typeof title === 'string' ? (
828
- <div
829
- style={{
830
- textAlign: 'center',
831
- fontSize: 13,
832
- fontWeight: 'bold',
833
- color: '#515151',
834
- marginTop: 12,
835
- marginBottom: 4,
836
- }}
837
- >
838
- {title}
839
- </div>
840
- ) : (
841
- title
842
- )
843
- ) : null;
844
-
845
- return (
846
- <Spin spinning={loading}>
847
- <div
848
- style={{
849
- position: 'relative',
850
- width: '100%',
851
- ...(titleNode
852
- ? { display: 'flex', flexDirection: 'column', height }
853
- : {}),
854
- }}
855
- >
856
- {titleNode}
857
- <div
858
- style={{
859
- position: 'relative',
860
- width: '100%',
861
- ...(titleNode ? { flex: 1, minHeight: 0 } : { height }),
862
- }}
863
- >
864
- <div
865
- ref={domRef}
866
- className={className}
867
- style={{
868
- width: '100%',
869
- height: titleNode ? '100%' : height,
870
- ...style,
871
- }}
872
- data-testid={testId}
873
- />
874
- {isEmptyData && !loading && (
875
- <div
876
- style={{
877
- position: 'absolute',
878
- inset: 0,
879
- display: 'flex',
880
- justifyContent: 'center',
881
- alignItems: 'center',
882
- }}
883
- >
884
- <Empty
885
- image={Empty.PRESENTED_IMAGE_SIMPLE}
886
- description="NO DATA"
887
- />
888
- </div>
889
- )}
890
- </div>
891
- </div>
892
- </Spin>
893
- );
894
- };
895
-
896
- export default BarChart;