@liujitcn/kratos-admin-bi 0.0.0-stage → 0.1.6

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 (166) hide show
  1. package/README.md +43 -2
  2. package/dist/package/declarations/index.d.ts +1 -0
  3. package/dist/package/declarations/src/api/bi/admin/v1/bi_card.d.ts +18 -0
  4. package/dist/package/declarations/src/api/bi/admin/v1/bi_card.js +46 -0
  5. package/dist/package/declarations/src/api/bi/admin/v1/bi_dashboard.d.ts +17 -0
  6. package/dist/package/declarations/src/api/bi/admin/v1/bi_dashboard.js +30 -0
  7. package/dist/package/declarations/src/api/bi/admin/v1/bi_query.d.ts +11 -0
  8. package/dist/package/declarations/src/api/bi/admin/v1/bi_query.js +41 -0
  9. package/dist/package/declarations/src/api/bi/admin/v1/bi_query_record.d.ts +10 -0
  10. package/dist/package/declarations/src/api/bi/admin/v1/bi_query_record.js +14 -0
  11. package/dist/package/declarations/src/api/bi/admin/v1/bi_source.d.ts +26 -0
  12. package/dist/package/declarations/src/api/bi/admin/v1/bi_source.js +46 -0
  13. package/dist/package/declarations/src/bi-core.d.ts +17 -0
  14. package/dist/package/declarations/src/bi-core.js +22 -0
  15. package/dist/package/declarations/src/bi-dashboard-schema.d.ts +31 -0
  16. package/dist/package/declarations/src/bi-dashboard-schema.js +39 -0
  17. package/dist/package/declarations/src/bi-messages.d.ts +247 -0
  18. package/dist/package/declarations/src/bi-messages.js +247 -0
  19. package/dist/package/declarations/src/bi-response.d.ts +10 -0
  20. package/dist/package/declarations/src/bi-response.js +33 -0
  21. package/dist/package/declarations/src/bi-vue.d.ts +10 -0
  22. package/dist/package/declarations/src/bi-vue.js +10 -0
  23. package/dist/package/declarations/src/card-schema.d.ts +30 -0
  24. package/dist/package/declarations/src/card-schema.js +87 -0
  25. package/dist/package/declarations/src/components/BiCardChartEditor.vue.d.ts +17 -0
  26. package/dist/package/declarations/src/components/BiCardChartEditor.vue.js +527 -0
  27. package/dist/package/declarations/src/components/BiCardFormDialog.vue.d.ts +20 -0
  28. package/dist/package/declarations/src/components/BiCardFormDialog.vue.js +495 -0
  29. package/dist/package/declarations/src/components/BiCardLibrary.vue.d.ts +3 -0
  30. package/dist/package/declarations/src/components/BiCardLibrary.vue.js +807 -0
  31. package/dist/package/declarations/src/components/BiCardVisualization.vue.d.ts +10 -0
  32. package/dist/package/declarations/src/components/BiCardVisualization.vue.js +97 -0
  33. package/dist/package/declarations/src/components/BiChart.vue.d.ts +20 -0
  34. package/dist/package/declarations/src/components/BiChart.vue.js +112 -0
  35. package/dist/package/declarations/src/components/BiDashboard.vue.d.ts +9 -0
  36. package/dist/package/declarations/src/components/BiDashboard.vue.js +81 -0
  37. package/dist/package/declarations/src/components/BiDashboardMenuDialog.vue.d.ts +12 -0
  38. package/dist/package/declarations/src/components/BiDashboardMenuDialog.vue.js +252 -0
  39. package/dist/package/declarations/src/components/BiDataCard.vue.d.ts +36 -0
  40. package/dist/package/declarations/src/components/BiDataCard.vue.js +372 -0
  41. package/dist/package/declarations/src/components/BiDesigner.vue.d.ts +17 -0
  42. package/dist/package/declarations/src/components/BiDesigner.vue.js +666 -0
  43. package/dist/package/declarations/src/components/BiSourceModelDialog.vue.d.ts +17 -0
  44. package/dist/package/declarations/src/components/BiSourceModelDialog.vue.js +2118 -0
  45. package/dist/package/declarations/src/components/BiWorkbenchPreview.vue.d.ts +7 -0
  46. package/dist/package/declarations/src/components/BiWorkbenchPreview.vue.js +176 -0
  47. package/dist/package/declarations/src/components/source-model-layout.d.ts +3 -0
  48. package/dist/package/declarations/src/components/source-model-layout.js +66 -0
  49. package/dist/package/declarations/src/dataset/index.d.ts +7 -0
  50. package/dist/package/declarations/src/dataset/index.js +25 -0
  51. package/dist/package/declarations/src/dataset/labels.d.ts +2 -0
  52. package/dist/package/declarations/src/dataset/labels.js +21 -0
  53. package/dist/package/declarations/src/dataset/transform.d.ts +20 -0
  54. package/dist/package/declarations/src/dataset/transform.js +173 -0
  55. package/dist/package/declarations/src/engine/chart-types.d.ts +14 -0
  56. package/dist/package/declarations/src/engine/chart-types.js +37 -0
  57. package/dist/package/declarations/src/engine/echarts.d.ts +16 -0
  58. package/dist/package/declarations/src/engine/echarts.js +491 -0
  59. package/dist/package/declarations/src/engine/types.d.ts +36 -0
  60. package/dist/package/declarations/src/engine/types.js +20 -0
  61. package/dist/package/declarations/src/env.d.ts +17 -0
  62. package/dist/package/declarations/src/env.js +67 -0
  63. package/dist/package/declarations/src/index.d.ts +1 -0
  64. package/dist/package/declarations/src/index.js +1 -0
  65. package/dist/package/declarations/src/locales/en-US.json +254 -0
  66. package/dist/package/declarations/src/locales/generated.d.ts +1021 -0
  67. package/dist/package/declarations/src/locales/generated.js +13 -0
  68. package/dist/package/declarations/src/locales/ja-JP.json +254 -0
  69. package/dist/package/declarations/src/locales/zh-CN.json +254 -0
  70. package/dist/package/declarations/src/locales/zh-TW.json +254 -0
  71. package/dist/package/declarations/src/module.d.ts +2 -0
  72. package/dist/package/declarations/src/module.js +9 -0
  73. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_card.d.ts +145 -0
  74. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_card.js +6 -0
  75. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_dashboard.d.ts +107 -0
  76. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_dashboard.js +6 -0
  77. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_query.d.ts +157 -0
  78. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_query.js +6 -0
  79. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_query_record.d.ts +83 -0
  80. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_query_record.js +15 -0
  81. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_source.d.ts +301 -0
  82. package/dist/package/declarations/src/rpc/bi/admin/v1/bi_source.js +6 -0
  83. package/dist/package/declarations/src/rpc/common/v1/types.d.ts +60 -0
  84. package/dist/package/declarations/src/rpc/common/v1/types.js +6 -0
  85. package/dist/package/declarations/src/schema/layout.d.ts +7 -0
  86. package/dist/package/declarations/src/schema/layout.js +52 -0
  87. package/dist/package/declarations/src/schema/types.d.ts +83 -0
  88. package/dist/package/declarations/src/schema/types.js +1 -0
  89. package/dist/package/declarations/src/theme/index.d.ts +29 -0
  90. package/dist/package/declarations/src/theme/index.js +83 -0
  91. package/dist/package/declarations/src/theme/palettes.d.ts +7 -0
  92. package/dist/package/declarations/src/theme/palettes.js +28 -0
  93. package/dist/package/declarations/src/theme/presets.d.ts +73 -0
  94. package/dist/package/declarations/src/theme/presets.js +235 -0
  95. package/dist/package/declarations/src/views/card/index.vue.d.ts +3 -0
  96. package/dist/package/declarations/src/views/card/index.vue.js +18 -0
  97. package/dist/package/declarations/src/views/dashboard/index.vue.d.ts +3 -0
  98. package/dist/package/declarations/src/views/dashboard/index.vue.js +107 -0
  99. package/dist/package/declarations/src/views/designer/index.vue.d.ts +3 -0
  100. package/dist/package/declarations/src/views/designer/index.vue.js +332 -0
  101. package/dist/package/declarations/src/views/manage/index.vue.d.ts +3 -0
  102. package/dist/package/declarations/src/views/manage/index.vue.js +325 -0
  103. package/dist/package/declarations/src/views/query/index.vue.d.ts +3 -0
  104. package/dist/package/declarations/src/views/query/index.vue.js +876 -0
  105. package/dist/package/declarations/src/views/source/index.vue.d.ts +3 -0
  106. package/dist/package/declarations/src/views/source/index.vue.js +343 -0
  107. package/dist/package/declarations/src/views/workbench/index.vue.d.ts +3 -0
  108. package/dist/package/declarations/src/views/workbench/index.vue.js +362 -0
  109. package/dist/package/src/api/bi/admin/v1/bi_card.ts +67 -0
  110. package/dist/package/src/api/bi/admin/v1/bi_dashboard.ts +51 -0
  111. package/dist/package/src/api/bi/admin/v1/bi_query.ts +55 -0
  112. package/dist/package/src/api/bi/admin/v1/bi_query_record.ts +25 -0
  113. package/dist/package/src/api/bi/admin/v1/bi_source.ts +80 -0
  114. package/dist/package/src/bi-core.ts +43 -0
  115. package/dist/package/src/bi-dashboard-schema.ts +69 -0
  116. package/dist/package/src/bi-messages.ts +249 -0
  117. package/dist/package/src/bi-response.ts +39 -0
  118. package/dist/package/src/bi-vue.ts +13 -0
  119. package/dist/package/src/card-schema.ts +111 -0
  120. package/dist/package/src/components/BiCardChartEditor.vue +139 -0
  121. package/dist/package/src/components/BiCardFormDialog.vue +289 -0
  122. package/dist/package/src/components/BiCardLibrary.vue +310 -0
  123. package/dist/package/src/components/BiCardVisualization.vue +95 -0
  124. package/dist/package/src/components/BiChart.vue +134 -0
  125. package/dist/package/src/components/BiDashboard.vue +53 -0
  126. package/dist/package/src/components/BiDashboardMenuDialog.vue +177 -0
  127. package/dist/package/src/components/BiDataCard.vue +231 -0
  128. package/dist/package/src/components/BiDesigner.vue +287 -0
  129. package/dist/package/src/components/BiSourceModelDialog.vue +846 -0
  130. package/dist/package/src/components/BiWorkbenchPreview.vue +131 -0
  131. package/dist/package/src/components/source-model-layout.ts +62 -0
  132. package/dist/package/src/dataset/index.ts +28 -0
  133. package/dist/package/src/dataset/labels.ts +19 -0
  134. package/dist/package/src/dataset/transform.ts +189 -0
  135. package/dist/package/src/engine/chart-types.ts +44 -0
  136. package/dist/package/src/engine/echarts.ts +568 -0
  137. package/dist/package/src/engine/types.ts +60 -0
  138. package/dist/package/src/env.ts +82 -0
  139. package/dist/package/src/index.ts +1 -0
  140. package/dist/package/src/locales/en-US.json +254 -0
  141. package/dist/package/src/locales/generated.ts +16 -0
  142. package/dist/package/src/locales/ja-JP.json +254 -0
  143. package/dist/package/src/locales/zh-CN.json +254 -0
  144. package/dist/package/src/locales/zh-TW.json +254 -0
  145. package/dist/package/src/module.ts +12 -0
  146. package/dist/package/src/rpc/bi/admin/v1/bi_card.ts +169 -0
  147. package/dist/package/src/rpc/bi/admin/v1/bi_dashboard.ts +126 -0
  148. package/dist/package/src/rpc/bi/admin/v1/bi_query.ts +187 -0
  149. package/dist/package/src/rpc/bi/admin/v1/bi_query_record.ts +98 -0
  150. package/dist/package/src/rpc/bi/admin/v1/bi_source.ts +338 -0
  151. package/dist/package/src/rpc/common/v1/types.ts +77 -0
  152. package/dist/package/src/schema/layout.ts +54 -0
  153. package/dist/package/src/schema/types.ts +103 -0
  154. package/dist/package/src/styles.scss +1 -0
  155. package/dist/package/src/theme/index.ts +108 -0
  156. package/dist/package/src/theme/palettes.ts +34 -0
  157. package/dist/package/src/theme/presets.ts +278 -0
  158. package/dist/package/src/views/card/index.vue +5 -0
  159. package/dist/package/src/views/dashboard/index.vue +58 -0
  160. package/dist/package/src/views/designer/index.vue +164 -0
  161. package/dist/package/src/views/manage/index.vue +276 -0
  162. package/dist/package/src/views/query/index.vue +593 -0
  163. package/dist/package/src/views/source/index.vue +214 -0
  164. package/dist/package/src/views/workbench/index.vue +208 -0
  165. package/package.json +67 -3
  166. package/tsconfig.json +12 -0
@@ -0,0 +1,43 @@
1
+ /** BI 图表内核:真实结果的字段映射、数据转换、图表引擎、布局与主题。 */
2
+
3
+ // Schema 与缺省
4
+ export * from "./schema/types";
5
+ export { flowPlace } from "./schema/layout";
6
+
7
+ // 数据集解析
8
+ export { getColumns, toNumber, unique } from "./dataset";
9
+
10
+ // 主题
11
+ export { BI_THEME_DARK, BI_THEME_LIGHT, detectDark, resolveTheme, watchDark } from "./theme";
12
+ export type { BiResolvedTheme } from "./theme";
13
+ export { BI_PALETTES, BI_PALETTE_KEYS, resolvePalette } from "./theme/palettes";
14
+ export {
15
+ BI_DASHBOARD_THEMES,
16
+ BI_SEMANTIC_COLORS,
17
+ BI_THEME_PRESET_KEYS,
18
+ getDashboardThemePreset,
19
+ resolveDashboardTheme,
20
+ resolveStageColors
21
+ } from "./theme/presets";
22
+ export type { BiDashboardThemePreset, BiStageColors } from "./theme/presets";
23
+
24
+ // 数据变换(过滤/聚合/排序/TopN + 字段类型推断 + 数值格式化)
25
+ export { applyFilters, aggregateRows, sortRows, transformRows, inferFieldType, formatNumber } from "./dataset/transform";
26
+ export type { BiFieldType } from "./dataset/transform";
27
+
28
+ // 引擎
29
+ export { createEchartsEngine, compileEcharts, installEchartsEngine } from "./engine/echarts";
30
+ export type { BiEChartsOption } from "./engine/echarts";
31
+ export { getEngine, hasEngine, registerEngine } from "./engine/types";
32
+ export type { BiChartEvent, ChartEngine, ChartHandle } from "./engine/types";
33
+
34
+ // 图型注册表(引擎适配器包扩展设计器图型)
35
+ export { registerChartType, getChartTypes, getEngineForType } from "./engine/chart-types";
36
+
37
+ // 文案包(纯数据)
38
+ export { BI_MESSAGES_ZH, BI_MESSAGES_EN } from "./bi-messages";
39
+
40
+ import { installEchartsEngine } from "./engine/echarts";
41
+
42
+ // 包加载即注册内置引擎
43
+ installEchartsEngine();
@@ -0,0 +1,69 @@
1
+ import { flowPlace } from "./schema/layout";
2
+ import { normalizeBiQueryResult, normalizeBiQuerySpec } from "./bi-response";
3
+ import type { BiCard } from "./rpc/bi/admin/v1/bi_card";
4
+ import type { BiDashboardDataResponse } from "./rpc/bi/admin/v1/bi_dashboard";
5
+ import type { BiQuerySpec } from "./rpc/bi/admin/v1/bi_query";
6
+
7
+ /** 仪表盘只保存名称、卡片引用与栅格位置,外观跟随管理端主题。 */
8
+ export interface DashboardLayout {
9
+ schemaVersion: 3;
10
+ name: string;
11
+ cards: DashboardCardLayout[];
12
+ }
13
+
14
+ /** 单张数据卡片的布局与服务端发布快照。 */
15
+ export interface DashboardCardLayout {
16
+ id: string;
17
+ card_id: number;
18
+ query_record_id?: number;
19
+ x?: number;
20
+ y?: number;
21
+ w: number;
22
+ h: number;
23
+ name?: string;
24
+ chart_type?: string;
25
+ chart_json?: string;
26
+ query?: BiQuerySpec;
27
+ }
28
+
29
+ /** 读取当前协议的仪表盘布局,不接收旧图表与数据集结构。 */
30
+ export function parseDashboardLayout(value: string): DashboardLayout {
31
+ if (!value) return { schemaVersion: 3, name: "", cards: [] };
32
+ const layout = JSON.parse(value) as DashboardLayout;
33
+ if (layout.schemaVersion !== 3 || !Array.isArray(layout.cards)) throw new Error("仪表盘布局格式无效");
34
+ return { schemaVersion: 3, name: layout.name, cards: layout.cards };
35
+ }
36
+
37
+ /** 将发布快照还原成只读数据卡片,保留当次图表配置。 */
38
+ export function dashboardSnapshotCard(item: DashboardCardLayout): BiCard {
39
+ return {
40
+ id: item.card_id,
41
+ tenant_id: 0,
42
+ project_id: 0,
43
+ owner_id: 0,
44
+ query_record_id: item.query_record_id || 0,
45
+ name: item.name || "",
46
+ source_code: item.query?.source_code || "",
47
+ query: item.query ? normalizeBiQuerySpec(item.query) : undefined,
48
+ chart_type: item.chart_type || "bar",
49
+ chart_json: item.chart_json || "",
50
+ refresh_seconds: 0,
51
+ is_shared: false,
52
+ updated_at: "",
53
+ category: "shared",
54
+ can_edit: false
55
+ };
56
+ }
57
+
58
+ /** 按发布快照匹配真实查询结果,并补齐 HTTP 省略的空集合。 */
59
+ export function dashboardResults(data: BiDashboardDataResponse) {
60
+ return new Map((data.cards ?? []).map(item => [item.item_id, item.result ? normalizeBiQueryResult(item.result) : undefined]));
61
+ }
62
+
63
+ /** 复用现有栅格算法整理卡片位置,避免拖动排序后互相覆盖。 */
64
+ export function reflowDashboardCards(cards: DashboardCardLayout[]): DashboardCardLayout[] {
65
+ return flowPlace(
66
+ cards.map(item => ({ ...item, x: undefined as number | undefined, y: undefined as number | undefined })),
67
+ 12
68
+ ).map(item => ({ ...item, x: item.x ?? 0, y: item.y ?? 0 }));
69
+ }
@@ -0,0 +1,249 @@
1
+ /**
2
+ * BI 文案包(纯数据,零依赖):渲染器只用 common.noData/Loading,
3
+ * 设计器(designer-vue)消费 designer.* 与 types.*。
4
+ * 键值取自 go-wind-admin 设计语言口径;改键同步两端包装包。
5
+ */
6
+
7
+ export const BI_MESSAGES_ZH = {
8
+ common: {
9
+ noData: "暂无数据",
10
+ loading: "加载中…",
11
+ back: "返回上一层",
12
+ resetDrill: "重置下钻",
13
+ exportImage: "导出图片",
14
+ fullscreen: "全屏",
15
+ },
16
+ designer: {
17
+ addChart: "新增图表",
18
+ addDataset: "新增数据集",
19
+ undo: "撤销",
20
+ redo: "重做",
21
+ compact: "整理布局",
22
+ import: "导入",
23
+ exportTemplate: "导出模板",
24
+ export: "导出",
25
+ preview: "预览",
26
+ edit: "编辑",
27
+ delete: "删除",
28
+ charts: "图表",
29
+ datasets: "数据集",
30
+ property: "属性",
31
+ selectChart: "点击画布中的图表进行编辑",
32
+ title: "标题",
33
+ type: "图型",
34
+ dataset: "数据集",
35
+ encoding: "视觉映射",
36
+ dimension: "维度",
37
+ measure: "度量",
38
+ series: "系列拆分",
39
+ position: "位置 (x / y)",
40
+ size: "大小 (宽 × 高)",
41
+ datasetName: "数据集名称",
42
+ datasetType: "类型",
43
+ rowsJson: "行数据 (JSON 数组)",
44
+ apiParams: "API 参数 (JSON)",
45
+ typeStatic: "静态数据",
46
+ typeApi: "API 取数",
47
+ noDataset: "请先创建数据集",
48
+ invalidJson: "JSON 格式错误",
49
+ save: "保存",
50
+ cancel: "取消",
51
+ importFailed: "导入失败",
52
+ confirmDeleteChart: "确定删除该图表吗?",
53
+ columns: "列",
54
+ tabData: "数据",
55
+ tabStyle: "样式",
56
+ tabLayout: "布局",
57
+ duplicate: "复制",
58
+ paste: "粘贴",
59
+ aggregation: "聚合方式",
60
+ aggNone: "不聚合",
61
+ aggSum: "求和",
62
+ aggAvg: "平均",
63
+ aggCount: "计数",
64
+ aggMax: "最大",
65
+ aggMin: "最小",
66
+ measures: "多度量(宽表)",
67
+ sortLabel: "排序",
68
+ sortByDim: "按维度",
69
+ sortByMeasure: "按度量",
70
+ asc: "升序",
71
+ desc: "降序",
72
+ topN: "取前 N 项",
73
+ filters: "过滤器",
74
+ addFilter: "+ 添加条件",
75
+ filterField: "字段",
76
+ opEq: "等于",
77
+ opNe: "不等于",
78
+ opGt: "大于",
79
+ opGte: "大于等于",
80
+ opLt: "小于",
81
+ opLte: "小于等于",
82
+ opContains: "包含",
83
+ opIn: "属于(逗号分隔)",
84
+ showLegend: "显示图例",
85
+ showLabel: "数值标签",
86
+ stack: "堆叠",
87
+ dataZoom: "数据缩放",
88
+ palette: "色盘",
89
+ paletteDefault: "默认",
90
+ paletteOcean: "海洋",
91
+ paletteSunset: "夕照",
92
+ paletteForest: "森林",
93
+ paletteMono: "墨阶",
94
+ numberFormat: "数字格式",
95
+ decimals: "小数位",
96
+ thousand: "千分位",
97
+ prefix: "前缀",
98
+ suffix: "后缀",
99
+ typeNumber: "数值",
100
+ typeString: "文本",
101
+ typeDate: "日期",
102
+ drillPath: "下钻路径",
103
+ addDrillLevel: "+ 添加下钻层级",
104
+ linkage: "跨图联动",
105
+ linkageTip: "开启后,点击图表以维度值过滤同数据集的其它图表",
106
+ templates: "模板",
107
+ themePreset: "仪表盘主题",
108
+ themeAuto: "跟随宿主亮暗",
109
+ },
110
+ types: {
111
+ bar: "柱状图",
112
+ line: "折线图",
113
+ area: "面积图",
114
+ pie: "饼图",
115
+ donut: "环形图",
116
+ scatter: "散点图",
117
+ radar: "雷达图",
118
+ gauge: "仪表图",
119
+ pivot: "透视表",
120
+ graph: "关系图",
121
+ funnel: "漏斗图",
122
+ treemap: "矩形树图",
123
+ sunburst: "旭日图",
124
+ sankey: "桑基图",
125
+ heatmap: "热力图",
126
+ },
127
+ };
128
+
129
+ export const BI_MESSAGES_EN = {
130
+ common: {
131
+ noData: "No data",
132
+ loading: "Loading…",
133
+ back: "Back",
134
+ resetDrill: "Reset drill",
135
+ exportImage: "Export PNG",
136
+ fullscreen: "Fullscreen",
137
+ },
138
+ designer: {
139
+ addChart: "Add Chart",
140
+ addDataset: "Add Dataset",
141
+ undo: "Undo",
142
+ redo: "Redo",
143
+ compact: "Tidy Layout",
144
+ import: "Import",
145
+ exportTemplate: "Export template",
146
+ export: "Export",
147
+ preview: "Preview",
148
+ edit: "Edit",
149
+ delete: "Delete",
150
+ charts: "Charts",
151
+ datasets: "Datasets",
152
+ property: "Properties",
153
+ selectChart: "Click a chart on the canvas to edit",
154
+ title: "Title",
155
+ type: "Type",
156
+ dataset: "Dataset",
157
+ encoding: "Encoding",
158
+ dimension: "Dimension",
159
+ measure: "Measure",
160
+ series: "Series",
161
+ position: "Position (x / y)",
162
+ size: "Size (W × H)",
163
+ datasetName: "Dataset name",
164
+ datasetType: "Type",
165
+ rowsJson: "Rows (JSON array)",
166
+ apiParams: "API params (JSON)",
167
+ typeStatic: "Static",
168
+ typeApi: "API",
169
+ noDataset: "Create a dataset first",
170
+ invalidJson: "Invalid JSON",
171
+ save: "Save",
172
+ cancel: "Cancel",
173
+ importFailed: "Import failed",
174
+ confirmDeleteChart: "Delete this chart?",
175
+ columns: "columns",
176
+ tabData: "Data",
177
+ tabStyle: "Style",
178
+ tabLayout: "Layout",
179
+ duplicate: "Duplicate",
180
+ paste: "Paste",
181
+ aggregation: "Aggregation",
182
+ aggNone: "None",
183
+ aggSum: "Sum",
184
+ aggAvg: "Average",
185
+ aggCount: "Count",
186
+ aggMax: "Max",
187
+ aggMin: "Min",
188
+ measures: "Multi-measure (wide)",
189
+ sortLabel: "Sort",
190
+ sortByDim: "By dimension",
191
+ sortByMeasure: "By measure",
192
+ asc: "Ascending",
193
+ desc: "Descending",
194
+ topN: "Top N",
195
+ filters: "Filters",
196
+ addFilter: "+ Add condition",
197
+ filterField: "Field",
198
+ opEq: "equals",
199
+ opNe: "not equals",
200
+ opGt: "greater than",
201
+ opGte: "≥",
202
+ opLt: "less than",
203
+ opLte: "≤",
204
+ opContains: "contains",
205
+ opIn: "in (comma separated)",
206
+ showLegend: "Show legend",
207
+ showLabel: "Data labels",
208
+ stack: "Stack",
209
+ dataZoom: "Data zoom",
210
+ palette: "Palette",
211
+ paletteDefault: "Default",
212
+ paletteOcean: "Ocean",
213
+ paletteSunset: "Sunset",
214
+ paletteForest: "Forest",
215
+ paletteMono: "Mono",
216
+ numberFormat: "Number format",
217
+ decimals: "Decimals",
218
+ thousand: "Thousands separator",
219
+ prefix: "Prefix",
220
+ suffix: "Suffix",
221
+ typeNumber: "Number",
222
+ typeString: "Text",
223
+ typeDate: "Date",
224
+ drillPath: "Drill path",
225
+ addDrillLevel: "+ Add drill level",
226
+ linkage: "Cross-filter",
227
+ linkageTip: "Clicking a chart filters sibling charts on the same dataset",
228
+ templates: "Templates",
229
+ themePreset: "Dashboard theme",
230
+ themeAuto: "Follow host",
231
+ },
232
+ types: {
233
+ bar: "Bar",
234
+ line: "Line",
235
+ area: "Area",
236
+ pie: "Pie",
237
+ donut: "Donut",
238
+ scatter: "Scatter",
239
+ radar: "Radar",
240
+ gauge: "Gauge",
241
+ pivot: "Pivot table",
242
+ graph: "Graph",
243
+ funnel: "Funnel",
244
+ treemap: "Treemap",
245
+ sunburst: "Sunburst",
246
+ sankey: "Sankey",
247
+ heatmap: "Heatmap",
248
+ },
249
+ };
@@ -0,0 +1,39 @@
1
+ import type { BiCard, BiWorkbench } from "./rpc/bi/admin/v1/bi_card";
2
+ import type { BiQueryResult, BiQuerySpec } from "./rpc/bi/admin/v1/bi_query";
3
+
4
+ /** 补齐 HTTP JSON 省略的查询集合字段,保留服务端返回的过滤、排序与时间范围。 */
5
+ export function normalizeBiQuerySpec(query: BiQuerySpec): BiQuerySpec {
6
+ return {
7
+ ...query,
8
+ dimensions: query.dimensions ?? [],
9
+ measures: query.measures ?? [],
10
+ filters: (query.filters ?? []).map(filter => ({ ...filter, values: filter.values ?? [] })),
11
+ orders: query.orders ?? []
12
+ };
13
+ }
14
+
15
+ /** 将无数据查询的省略字段统一为可渲染的空结果。 */
16
+ export function normalizeBiQueryResult(result: BiQueryResult): BiQueryResult {
17
+ return {
18
+ ...result,
19
+ columns: result.columns ?? [],
20
+ rows: (result.rows ?? []).map(row => ({ values: row.values ?? [] })),
21
+ truncated: result.truncated ?? false,
22
+ elapsed_ms: result.elapsed_ms ?? 0,
23
+ query_record_id: result.query_record_id ?? 0
24
+ };
25
+ }
26
+
27
+ /** 在卡片 API 边界补齐查询配置,页面不再重复处理缺省集合。 */
28
+ export function normalizeBiCard(card: BiCard): BiCard {
29
+ return { ...card, query: card.query ? normalizeBiQuerySpec(card.query) : undefined };
30
+ }
31
+
32
+ /** 新账号和清空后的工作台使用相同的空集合结构。 */
33
+ export function normalizeBiWorkbench(workbench: BiWorkbench): BiWorkbench {
34
+ return {
35
+ dashboard_ids: workbench.dashboard_ids ?? [],
36
+ favorite_ids: workbench.favorite_ids ?? [],
37
+ dashboards: workbench.dashboards ?? []
38
+ };
39
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Vue 3 BI 仪表盘:BiDashboard 只读渲染器 + BiDesigner 画布设计器。
3
+ * 数据查询与卡片配置由服务端提供,设计器仅调整卡片布局。
4
+ */
5
+ import "./styles.scss";
6
+
7
+ export { default as BiDashboard } from "./components/BiDashboard.vue";
8
+ export { default as BiDesigner } from "./components/BiDesigner.vue";
9
+ export { default as BiChart } from "./components/BiChart.vue";
10
+
11
+ // 环境注入(主题跟随 / resolvers / 项目 i18n)
12
+ export { provideBiEnv, useBiEnv, useBiTheme, useBiI18n } from "./env";
13
+ export type { BiEnv } from "./env";
@@ -0,0 +1,111 @@
1
+ import type { BiDashboard } from "./rpc/bi/admin/v1/bi_dashboard";
2
+ import type { BiChartEncoding, BiChartStyle, BiChartSchema, BiRow } from "./schema/types";
3
+ import type { BiCard } from "./rpc/bi/admin/v1/bi_card";
4
+ import type { BiQueryResult, BiSourceDescriptor } from "./rpc/bi/admin/v1/bi_query";
5
+
6
+ /** 将卡片查询结果映射到现有图表引擎,保留分组及全部所选指标。 */
7
+ export function buildCardChart(
8
+ card: BiCard,
9
+ result: BiQueryResult
10
+ ): { chart: BiChartSchema; rows: BiRow[]; metrics: Array<{ code: string; name: string; value: string }>; metricOnly: boolean } {
11
+ const config = parseCardChart(card);
12
+ const numericFields = result.columns.filter(column => column.type === "number");
13
+ const measure =
14
+ config.encoding.measure ||
15
+ (card.chart_type === "scatter" ? numericFields[1]?.code : undefined) ||
16
+ card.query?.measures[0]?.code ||
17
+ result.columns.find(column => column.type === "number")?.code ||
18
+ result.columns[0]?.code ||
19
+ "";
20
+ const dimension =
21
+ config.encoding.dimension ||
22
+ (card.chart_type === "scatter" ? numericFields[0]?.code : undefined) ||
23
+ (card.query ? card.query.dimensions[0] : result.columns.find(column => column.code !== measure)?.code);
24
+ const rows = result.rows.map(row =>
25
+ Object.fromEntries(result.columns.map((column, index) => [column.code, row.values[index] ?? ""]))
26
+ );
27
+ const measures = config.encoding.measures?.length
28
+ ? config.encoding.measures
29
+ : card.query?.measures.length
30
+ ? card.query.measures.map(item => item.code)
31
+ : [measure];
32
+ return {
33
+ chart: {
34
+ id: `card_${card.id}`,
35
+ datasetId: `card_${card.id}`,
36
+ type: card.chart_type,
37
+ encoding: {
38
+ dimension,
39
+ measure,
40
+ measures: ["bar", "line", "area"].includes(card.chart_type) && measures.length > 1 ? measures : undefined,
41
+ series: card.chart_type === "scatter" ? undefined : card.query?.dimensions[1],
42
+ ...config.encoding
43
+ },
44
+ aggregation: "none",
45
+ style: {
46
+ showLabel: false,
47
+ showLegend: measures.length > 1 || card.chart_type === "pie" || card.chart_type === "donut",
48
+ ...config.style
49
+ }
50
+ },
51
+ rows,
52
+ metrics: measures.map(code => ({
53
+ code,
54
+ name: result.columns.find(column => column.code === code)?.name || code,
55
+ value: String(rows[0]?.[code] ?? "—")
56
+ })),
57
+ metricOnly: card.chart_type === "metric"
58
+ };
59
+ }
60
+
61
+ /** 数据卡片统一保存字段映射与受控样式。 */
62
+ export interface CardChartConfig {
63
+ encoding: BiChartEncoding;
64
+ style: Pick<BiChartStyle, "showLabel" | "showLegend" | "stack" | "dataZoom" | "palette">;
65
+ }
66
+
67
+ /** 从服务端配置读取图表字段,预览卡片允许使用默认映射。 */
68
+ export function parseCardChart(card: Pick<BiCard, "chart_json">): CardChartConfig {
69
+ return card.chart_json
70
+ ? (JSON.parse(card.chart_json) as CardChartConfig)
71
+ : { encoding: {}, style: { showLegend: true, showLabel: false } };
72
+ }
73
+
74
+ /** 仅在卡片明确指定时间字段或只有一个可过滤日期分组时开放周期切换。 */
75
+ export function supportsCardPeriod(card: BiCard, source?: BiSourceDescriptor): boolean {
76
+ const fields =
77
+ source?.dimensions.filter(
78
+ dimension =>
79
+ dimension.type === "date" &&
80
+ dimension.filterable &&
81
+ (card.query?.time_range
82
+ ? dimension.code === card.query.time_range.field
83
+ : card.query?.dimensions.includes(dimension.code))
84
+ ) ?? [];
85
+ return fields.length === 1;
86
+ }
87
+
88
+ /** 计算刷新等待时间,86400对应浏览器本地时区的下一次02:00。 */
89
+ export function cardRefreshDelay(seconds: number, now = new Date()): number {
90
+ if (seconds !== 86400) return seconds * 1000;
91
+ const next = new Date(now.getTime());
92
+ next.setHours(2, 0, 0, 0);
93
+ if (next.getTime() <= now.getTime()) next.setDate(next.getDate() + 1);
94
+ return next.getTime() - now.getTime();
95
+ }
96
+
97
+ /** 按当前四种界面语言的分组习惯显示数字字符串,不转换浮点数或丢弃小数位。 */
98
+ export function formatCardMetric(value: string): string {
99
+ if (!/^[+-]?\d+(?:\.\d+)?$/.test(value)) return value;
100
+ const [integer, fraction] = value.split(".");
101
+ return integer.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (fraction === undefined ? "" : "." + fraction);
102
+ }
103
+
104
+ /** 保持工作台入口顺序,忽略已删除或撤销权限的仪表盘。 */
105
+ export function orderWorkbenchDashboards(ids: number[], dashboards: BiDashboard[]): BiDashboard[] {
106
+ const byID = new Map(dashboards.map(item => [item.id, item]));
107
+ return ids.flatMap(id => {
108
+ const item = byID.get(id);
109
+ return item ? [item] : [];
110
+ });
111
+ }
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <div class="bi-card-chart-editor">
3
+ <div class="bi-card-chart-editor__types">
4
+ <el-button
5
+ v-for="type in types"
6
+ :key="type"
7
+ :type="type === chartType ? 'primary' : 'default'"
8
+ :plain="type !== chartType"
9
+ :disabled="Boolean(reason(type))"
10
+ :title="reason(type)"
11
+ @click="changeType(type)"
12
+ >{{ type === "metric" ? t("bi.card.chart.metric") : messages(`types.${type}`) }}</el-button
13
+ >
14
+ </div>
15
+ <p class="bi-card-chart-editor__hint">{{ t("bi.card.chart_hint") }}</p>
16
+ <el-form label-position="top">
17
+ <el-form-item v-if="chartType !== 'metric' && chartType !== 'gauge'" :label="t('bi.card.dimension_field')">
18
+ <el-select :model-value="modelValue.encoding.dimension || dimensionFields[0]?.code" @change="patchEncoding({ dimension: $event })"
19
+ ><el-option v-for="field in dimensionFields" :key="field.code" :value="field.code" :label="field.name"
20
+ /></el-select>
21
+ </el-form-item>
22
+ <el-form-item :label="t('bi.card.value_field')"
23
+ ><el-select :model-value="modelValue.encoding.measure || numbers[chartType === 'scatter' ? 1 : 0]?.code" @change="patchEncoding({ measure: $event })"
24
+ ><el-option v-for="field in numbers" :key="field.code" :value="field.code" :label="field.name" /></el-select
25
+ ></el-form-item>
26
+ <el-form-item v-if="['sankey', 'heatmap', 'sunburst'].includes(chartType)" :label="t('bi.card.series_field')"
27
+ ><el-select :model-value="modelValue.encoding.series || categories[1]?.code" @change="patchEncoding({ series: $event })"
28
+ ><el-option v-for="field in categories" :key="field.code" :value="field.code" :label="field.name" /></el-select
29
+ ></el-form-item>
30
+ <el-form-item v-if="['bar', 'line', 'area'].includes(chartType)" :label="t('bi.card.measure')"
31
+ ><el-checkbox-group
32
+ :model-value="modelValue.encoding.measures || []"
33
+ @change="patchEncoding({ measures: $event as string[] })"
34
+ ><el-checkbox v-for="field in numbers" :key="field.code" :value="field.code">{{
35
+ field.name
36
+ }}</el-checkbox></el-checkbox-group
37
+ ></el-form-item
38
+ >
39
+ <div class="bi-card-chart-editor__style">
40
+ <el-checkbox :model-value="modelValue.style.showLegend" @change="patchStyle({ showLegend: Boolean($event) })">{{
41
+ t("bi.card.show_legend")
42
+ }}</el-checkbox
43
+ ><el-checkbox :model-value="modelValue.style.showLabel" @change="patchStyle({ showLabel: Boolean($event) })">{{
44
+ t("bi.card.show_label")
45
+ }}</el-checkbox
46
+ ><el-checkbox :model-value="modelValue.style.stack" @change="patchStyle({ stack: Boolean($event) })">{{
47
+ t("bi.card.stack")
48
+ }}</el-checkbox
49
+ ><el-checkbox :model-value="modelValue.style.dataZoom" @change="patchStyle({ dataZoom: Boolean($event) })">{{
50
+ t("bi.card.data_zoom")
51
+ }}</el-checkbox>
52
+ </div>
53
+ </el-form>
54
+ </div>
55
+ </template>
56
+ <script setup lang="ts">
57
+ import { computed } from "vue";
58
+ import { t } from "@liujitcn/kratos-admin-core";
59
+ import type { BiQueryResult, BiQuerySpec } from "../rpc/bi/admin/v1/bi_query";
60
+ import type { CardChartConfig } from "../card-schema";
61
+ import type { BiChartEncoding } from "../schema/types";
62
+ import { getChartTypes } from "../engine/chart-types";
63
+ import { useBiI18n } from "../env";
64
+ const props = defineProps<{ modelValue: CardChartConfig; chartType: string; query: BiQuerySpec; result?: BiQueryResult }>();
65
+ const emit = defineEmits<{ "update:modelValue": [value: CardChartConfig]; "update:chartType": [value: string] }>();
66
+ const { t: messages } = useBiI18n();
67
+ const types = [...getChartTypes(), "metric"];
68
+ const numbers = computed(
69
+ () =>
70
+ props.result?.columns.filter(field => field.type === "number") ??
71
+ props.query.measures.map(field => ({ code: field.code, name: field.code, type: "number" }))
72
+ );
73
+ const categories = computed(() =>
74
+ props.query.dimensions.map(
75
+ code => props.result?.columns.find(field => field.code === code) ?? { code, name: code, type: "string" }
76
+ )
77
+ );
78
+ const dimensionFields = computed(() => (props.chartType === "scatter" ? numbers.value : categories.value));
79
+ /** 根据真实结果结构启用图型,避免产生不能渲染的卡片。 */
80
+ function reason(type: string): string {
81
+ if (["metric", "gauge"].includes(type)) return props.query.dimensions.length ? t("bi.card.need_ungrouped") : "";
82
+ if (type === "scatter") return numbers.value.length < 2 ? t("bi.card.need_two_numbers") : "";
83
+ if (["sankey", "heatmap", "sunburst"].includes(type))
84
+ return categories.value.length < 2 ? t("bi.card.need_two_dimensions") : "";
85
+ return categories.value.length ? "" : t("bi.card.need_dimension");
86
+ }
87
+ /** 切换图型时复用当前查询结果,并补齐该图型的默认字段映射。 */
88
+ function changeType(type: string) {
89
+ emit("update:chartType", type);
90
+ emit("update:modelValue", {
91
+ encoding: {
92
+ dimension: type === "scatter" ? numbers.value[0]?.code : categories.value[0]?.code,
93
+ measure: type === "scatter" ? numbers.value[1]?.code : numbers.value[0]?.code,
94
+ series: type === "scatter" ? undefined : categories.value[1]?.code,
95
+ measures:
96
+ ["bar", "line", "area"].includes(type) && categories.value.length < 2 ? numbers.value.map(field => field.code) : undefined
97
+ },
98
+ style: { ...props.modelValue.style }
99
+ });
100
+ }
101
+ /** 同步字段映射,不重新执行已完成的查询。 */
102
+ function patchEncoding(value: Partial<BiChartEncoding>) {
103
+ emit("update:modelValue", { ...props.modelValue, encoding: { ...props.modelValue.encoding, ...value } });
104
+ }
105
+ /** 同步受控样式选项。 */
106
+ function patchStyle(value: Partial<CardChartConfig["style"]>) {
107
+ emit("update:modelValue", { ...props.modelValue, style: { ...props.modelValue.style, ...value } });
108
+ }
109
+ </script>
110
+ <style scoped>
111
+ .bi-card-chart-editor__types {
112
+ display: grid;
113
+ grid-template-columns: repeat(4, minmax(0, 1fr));
114
+ gap: 8px;
115
+ }
116
+ .bi-card-chart-editor__types :deep(.el-button) {
117
+ margin: 0;
118
+ padding: 8px;
119
+ min-width: 0;
120
+ }
121
+ .bi-card-chart-editor__hint {
122
+ color: var(--el-text-color-secondary);
123
+ font-size: 12px;
124
+ margin: 10px 0 16px;
125
+ }
126
+ .bi-card-chart-editor__style {
127
+ display: flex;
128
+ flex-wrap: wrap;
129
+ gap: 8px 18px;
130
+ }
131
+ .bi-card-chart-editor :deep(.el-select) {
132
+ width: 100%;
133
+ }
134
+ @media (max-width: 600px) {
135
+ .bi-card-chart-editor__types {
136
+ grid-template-columns: repeat(3, minmax(0, 1fr));
137
+ }
138
+ }
139
+ </style>