@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,214 @@
1
+ <template>
2
+ <div class="table-box">
3
+ <ProTable ref="table" row-key="id" :columns="columns" :header-actions="headerActions" :request-api="requestTable" />
4
+ <FormDialog
5
+ ref="dialogRef"
6
+ v-model="dialog.visible"
7
+ :title="dialog.editing ? t('bi.source.title.edit') : t('bi.source.title.create')"
8
+ width="min(1040px, 96vw)"
9
+ label-width="10em"
10
+ :model="form"
11
+ :fields="fields"
12
+ :rules="rules"
13
+ :form-props="{ disabled: testing }"
14
+ @confirm="submit"
15
+ @close="resetForm"
16
+ >
17
+ <template #footer>
18
+ <div class="dialog-footer">
19
+ <el-button :disabled="testing" @click="dialog.visible = false">{{ t("common.action.cancel") }}</el-button>
20
+ <el-button type="primary" plain :icon="Connection" :loading="testing" @click="testSource">{{ t("bi.source.action.test") }}</el-button>
21
+ <el-button type="primary" :disabled="testing" @click="submit">{{ t("common.action.confirm") }}</el-button>
22
+ </div>
23
+ </template>
24
+ </FormDialog>
25
+ <BiSourceModelDialog v-model="modelDialog" :source="modelSource" @saved="handleModelSaved" />
26
+ </div>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ import { computed, reactive, ref } from "vue";
31
+ import { ElMessage, ElMessageBox } from "element-plus";
32
+ import { CirclePlus, Connection, Delete, EditPen, SetUp } from "@element-plus/icons-vue";
33
+ import ProTable from "@liujitcn/kratos-admin-core/components/ProTable";
34
+ import FormDialog from "@liujitcn/kratos-admin-core/components/Dialog/FormDialog.vue";
35
+ import type { ProFormField } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
36
+ import type { ColumnProps, HeaderActionProps, ProTableInstance } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
37
+ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
38
+ import { encodeSecretFields } from "@liujitcn/kratos-admin-core/security";
39
+ import { buildPageRequest } from "@liujitcn/kratos-admin-core/table";
40
+ import { useTenantScope } from "@liujitcn/kratos-admin-core/tenant";
41
+ import { t } from "@liujitcn/kratos-admin-core";
42
+ import { defBiSourceService } from "../../api/bi/admin/v1/bi_source";
43
+ import BiSourceModelDialog from "../../components/BiSourceModelDialog.vue";
44
+ import type { BiSource, BiSourceForm, PageBiSourceRequest } from "../../rpc/bi/admin/v1/bi_source";
45
+
46
+ interface BiSourceFormState extends BiSourceForm {
47
+ password_configured: boolean;
48
+ }
49
+
50
+ defineOptions({name: "BiSource", inheritAttrs: false});
51
+
52
+ const { BUTTONS } = useAuthButtons();
53
+ const { isDefaultTenant } = useTenantScope();
54
+ const table = ref<ProTableInstance>();
55
+ const dialogRef = ref<InstanceType<typeof FormDialog>>();
56
+ const dialog = reactive({visible: false, editing: false});
57
+ const form = reactive<BiSourceFormState>(defaultForm());
58
+ const modelDialog = ref(false);
59
+ const modelSource = ref<BiSource>();
60
+ const editingModelConfigured = ref(false);
61
+ const testing = ref(false);
62
+ const driverOptions = [
63
+ {label: "MySQL", value: "mysql"},
64
+ {label: "PostgreSQL", value: "postgres"},
65
+ {label: "Doris", value: "doris"},
66
+ {label: "TiDB", value: "tidb"}
67
+ ];
68
+ const driverDefaultPorts: Record<string, number> = {mysql: 3306, postgres: 5432, doris: 9030, tidb: 4000};
69
+
70
+ const fields = computed<ProFormField[]>(() => [
71
+ {prop: "code", label: t("bi.source.field.code"), component: "input", colSpan: 12, props: {maxlength: 128, disabled: dialog.editing}},
72
+ {prop: "name", label: t("bi.source.field.name"), component: "input", colSpan: 12, props: {maxlength: 128}},
73
+ {prop: "description", label: t("bi.source.field.description"), component: "input", colSpan: 24, props: {maxlength: 500}},
74
+ {
75
+ prop: "source_name",
76
+ label: t("bi.source.field.source_name"),
77
+ component: "input",
78
+ colSpan: 24,
79
+ visible: () => isDefaultTenant.value,
80
+ props: {maxlength: 64, placeholder: t("bi.source.placeholder.source_name")}
81
+ },
82
+ {prop: "driver", label: t("bi.source.field.driver"), component: "select", colSpan: 12, options: driverOptions, props: {onChange: handleDriverChange}},
83
+ ...(!form.source_name ? [
84
+ {prop: "host", label: t("bi.source.field.host"), component: "input" as const, colSpan: 12, props: {maxlength: 255}},
85
+ {prop: "port", label: t("bi.source.field.port"), component: "input-number" as const, colSpan: 12, props: {min: 1, max: 65535, precision: 0, controlsPosition: "right"}},
86
+ {prop: "database_name", label: t("bi.source.field.database_name"), component: "input" as const, colSpan: 12, props: {maxlength: 128}},
87
+ {prop: "username", label: t("bi.source.field.username"), component: "input" as const, colSpan: 12, props: {maxlength: 128, autocomplete: "off"}},
88
+ {prop: "password", label: t("bi.source.field.password"), component: "input" as const, colSpan: 12, secret: {resource: "bi_source", field: "password"}, props: {type: "password", showPassword: true, maxlength: 512, autocomplete: "new-password", placeholder: form.password_configured ? t("bi.source.placeholder.keep_password") : t("bi.source.placeholder.password")}},
89
+ {prop: "ssl_mode", label: t("bi.source.field.ssl_mode"), component: "input" as const, colSpan: 12, props: {maxlength: 32, placeholder: "disable"}}
90
+ ] : []),
91
+ {prop: "schema_name", label: t("bi.source.field.schema_name"), component: "input", colSpan: 12, props: {maxlength: 128}},
92
+ {prop: "max_rows", label: t("bi.source.field.max_rows"), component: "input-number", colSpan: 12, props: {min: 1, max: 1000, precision: 0, controlsPosition: "right"}}
93
+ ]);
94
+
95
+ const rules = computed(() => ({
96
+ code: [{required: true, message: t("bi.source.validation.code"), trigger: "blur"}],
97
+ name: [{required: true, message: t("bi.source.validation.name"), trigger: "blur"}],
98
+ driver: [{required: true, message: t("bi.source.validation.driver"), trigger: "change"}],
99
+ host: [{required: !form.source_name, message: t("bi.source.validation.host"), trigger: "blur"}],
100
+ database_name: [{required: !form.source_name, message: t("bi.source.validation.database_name"), trigger: "blur"}],
101
+ username: [{required: !form.source_name, message: t("bi.source.validation.username"), trigger: "blur"}],
102
+ password: [{required: !form.source_name && !dialog.editing, message: t("bi.source.validation.password"), trigger: "blur"}]
103
+ }));
104
+
105
+ const columns = computed<ColumnProps[]>(() => [
106
+ {prop: "code", label: t("bi.source.field.code"), minWidth: 150, search: {el: "input"}},
107
+ {prop: "name", label: t("bi.source.field.name"), minWidth: 140},
108
+ {prop: "driver", label: t("bi.source.field.driver"), width: 110},
109
+ {prop: "source_name", label: t("bi.source.field.connection"), minWidth: 190, render: ({row}) => row.host ? `${row.host}:${row.port}/${row.database_name}` : row.source_name},
110
+ {prop: "table_count", label: t("bi.source.model.field.tables"), width: 120, render: ({row}) => row.model_configured ? String(row.table_count) : t("bi.source.value.not_configured")},
111
+ {prop: "password_configured", label: t("bi.source.field.password"), width: 120, render: ({row}) => row.password_configured ? t("bi.source.value.configured") : t("bi.source.value.not_configured")},
112
+ {prop: "status", label: t("common.field.status"), width: 100, cellType: "status", statusProps: {activeValue: 1, inactiveValue: 2, activeText: t("common.status.enabled"), inactiveText: t("common.status.disabled"), disabled: scope => !BUTTONS.value["bi:source:status"] || !(scope.row as BiSource).model_configured, beforeChange: async scope => { await setStatus(scope.row as BiSource); return true; }}},
113
+ {prop: "updated_at", label: t("common.field.updated_at"), minWidth: 175},
114
+ {prop: "operation", label: t("common.field.operation"), cellType: "actions", fixed: "right", width: 250, actions: [
115
+ {label: t("bi.source.model.action.configure"), link: true, icon: SetUp, hidden: () => !BUTTONS.value["bi:source:update"], onClick: scope => openModel((scope.row as BiSource).id)},
116
+ {label: t("common.action.edit"), link: true, icon: EditPen, hidden: () => !BUTTONS.value["bi:source:update"], onClick: scope => openDialog((scope.row as BiSource).id)},
117
+ {label: t("common.action.delete"), type: "danger", link: true, icon: Delete, hidden: () => !BUTTONS.value["bi:source:delete"], onClick: scope => remove(scope.row as BiSource)}
118
+ ]}
119
+ ]);
120
+
121
+ const headerActions = computed<HeaderActionProps[]>(() => [{label: t("common.action.create"), type: "primary", icon: CirclePlus, hidden: () => !BUTTONS.value["bi:source:create"], onClick: () => openDialog()}]);
122
+
123
+ /** 创建空的数据源连接表单。 */
124
+ function defaultForm(): BiSourceFormState {
125
+ return {id: 0, code: "", name: "", description: "", source_name: "", driver: "mysql", host: "", port: 3306, database_name: "", username: "", password: undefined, password_configured: false, ssl_mode: "disable", schema_name: "", max_rows: 100, status: 2};
126
+ }
127
+
128
+ /** 根据所选数据库驱动更新默认端口。 */
129
+ function handleDriverChange(driver: string) {
130
+ form.port = driverDefaultPorts[driver] ?? 3306;
131
+ }
132
+
133
+ /** 请求数据源列表。 */
134
+ async function requestTable(params: Record<string, unknown>) {
135
+ const data = await defBiSourceService.PageBiSource(buildPageRequest<PageBiSourceRequest>(params as unknown as PageBiSourceRequest));
136
+ return {data: {list: data.sources ?? [], total: data.total}};
137
+ }
138
+
139
+ /** 打开连接表单,普通租户的已有宿主绑定需要改为独立连接。 */
140
+ async function openDialog(id?: number) {
141
+ const source = id ? await defBiSourceService.GetBiSource({id}) : undefined;
142
+ await dialogRef.value?.open({
143
+ load: () => source,
144
+ commit: value => {
145
+ Object.assign(form, defaultForm(), value ?? {});
146
+ if (!isDefaultTenant.value) form.source_name = "";
147
+ dialog.editing = Boolean(id);
148
+ editingModelConfigured.value = Boolean((value as BiSource | undefined)?.model_configured);
149
+ }
150
+ });
151
+ }
152
+
153
+ /** 保存连接配置,连接变化导致模型失效时重新配置。 */
154
+ async function submit() {
155
+ const valid = await dialogRef.value?.validate();
156
+ if (!valid) return;
157
+ const encoded = await encodeSecretFields(fields.value, form);
158
+ const {password_configured: _passwordConfigured, ...source} = encoded as BiSourceFormState;
159
+ const result = dialog.editing ? await defBiSourceService.UpdateBiSource({source}) : await defBiSourceService.CreateBiSource({source});
160
+ ElMessage.success(t(dialog.editing ? "bi.source.message.update_success" : "bi.source.message.create_success"));
161
+ dialog.visible = false;
162
+ resetForm();
163
+ table.value?.getTableList();
164
+ if (editingModelConfigured.value && !result.model_configured) await openModel(result);
165
+ }
166
+
167
+ /** 测试表单中的连接,不要求先选择表。 */
168
+ async function testSource() {
169
+ const valid = await dialogRef.value?.validate();
170
+ if (!valid) return;
171
+ testing.value = true;
172
+ try {
173
+ const encoded = await encodeSecretFields(fields.value, form);
174
+ const {password_configured: _passwordConfigured, ...source} = encoded as BiSourceFormState;
175
+ const result = await defBiSourceService.TestBiSource({source});
176
+ ElMessage[result.success ? "success" : "warning"](result.message || t(result.success ? "bi.source.message.test_success" : "bi.source.message.test_failed"));
177
+ } finally {
178
+ testing.value = false;
179
+ }
180
+ }
181
+
182
+ /** 打开表结构与关系模型配置。 */
183
+ async function openModel(sourceOrID: BiSource | number) {
184
+ modelSource.value = typeof sourceOrID === "number" ? await defBiSourceService.GetBiSource({id: sourceOrID}) : sourceOrID;
185
+ modelDialog.value = true;
186
+ }
187
+
188
+ /** 保存模型后刷新连接列表。 */
189
+ function handleModelSaved(source: BiSource) {
190
+ modelSource.value = source;
191
+ table.value?.getTableList();
192
+ }
193
+
194
+ /** 切换数据源启用状态。 */
195
+ async function setStatus(row: BiSource) {
196
+ await defBiSourceService.SetBiSourceStatus({id: row.id, status: row.status === 1 ? 2 : 1});
197
+ table.value?.getTableList();
198
+ }
199
+
200
+ /** 删除数据源连接。 */
201
+ async function remove(row: BiSource) {
202
+ await ElMessageBox.confirm(t("bi.source.dialog.delete_confirm", {name: row.name}), t("common.title.warning"));
203
+ await defBiSourceService.DeleteBiSource({id: row.id});
204
+ ElMessage.success(t("bi.source.message.delete_success"));
205
+ table.value?.getTableList();
206
+ }
207
+
208
+ /** 重置表单和校验状态。 */
209
+ function resetForm() {
210
+ Object.assign(form, defaultForm());
211
+ dialog.editing = false;
212
+ editingModelConfigured.value = false;
213
+ }
214
+ </script>
@@ -0,0 +1,208 @@
1
+ <template>
2
+ <main class="bi-workbench">
3
+ <el-skeleton v-if="loading" :rows="6" animated /><el-empty
4
+ v-else-if="!dashboards.length"
5
+ :description="t('bi.workbench.empty')"
6
+ ><el-button @click="router.push('/bi/manage')">{{ t("bi.dashboard.manage") }}</el-button></el-empty
7
+ >
8
+ <div v-else class="bi-workbench__grid" :aria-busy="saving">
9
+ <article
10
+ v-for="(item, index) in dashboards"
11
+ :key="item.id"
12
+ class="bi-workbench__entry"
13
+ :class="{ 'is-dragging': dragged === index }"
14
+ :draggable="!saving"
15
+ tabindex="0"
16
+ :aria-label="`${item.name}:${t('bi.workbench.drag')}`"
17
+ aria-keyshortcuts="Alt+ArrowLeft Alt+ArrowRight"
18
+ @dragstart="startDrag($event, index)"
19
+ @dragend="dragged = -1"
20
+ @dragover.prevent
21
+ @drop.prevent="move(dragged, index)"
22
+ @keydown.alt.left.prevent="move(index, index - 1)"
23
+ @keydown.alt.right.prevent="move(index, index + 1)"
24
+ >
25
+ <BiWorkbenchPreview :key="`${item.id}:${item.published_version}`" :dashboard="item" />
26
+ <div class="bi-workbench__info">
27
+ <div class="bi-workbench__title">
28
+ <h3 :title="item.name">{{ item.name }}</h3>
29
+ <el-tag size="small" effect="light">{{ t("bi.dashboard.status_published") }}</el-tag>
30
+ </div>
31
+ <p class="bi-workbench__meta">
32
+ {{ t("bi.card.total", { count: parseDashboardLayout(item.schema_json).cards.length }) }} · v{{
33
+ item.published_version
34
+ }}
35
+ </p>
36
+ <p v-if="item.description" class="bi-workbench__description">{{ item.description }}</p>
37
+ <footer>
38
+ <el-button type="primary" @click="router.push(`/bi/dashboard/${item.id}`)"
39
+ >{{ t("bi.workbench.open_dashboard") }}<el-icon class="el-icon--right"><ArrowRight /></el-icon
40
+ ></el-button>
41
+ </footer>
42
+ </div>
43
+ </article>
44
+ </div>
45
+ </main>
46
+ </template>
47
+ <script setup lang="ts">
48
+ import { onActivated, onMounted, ref } from "vue";
49
+ import { useRouter } from "vue-router";
50
+ import { t } from "@liujitcn/kratos-admin-core";
51
+ import type { BiDashboard } from "../../rpc/bi/admin/v1/bi_dashboard";
52
+ import { orderWorkbenchDashboards } from "../../card-schema";
53
+ import { defBiCardService } from "../../api/bi/admin/v1/bi_card";
54
+ import { parseDashboardLayout } from "../../bi-dashboard-schema";
55
+ import BiWorkbenchPreview from "../../components/BiWorkbenchPreview.vue";
56
+ defineOptions({ name: "BiWorkbench", inheritAttrs: false });
57
+ const router = useRouter(),
58
+ dashboards = ref<BiDashboard[]>([]),
59
+ loading = ref(false),
60
+ saving = ref(false),
61
+ dragged = ref(-1);
62
+ let loaded = false;
63
+ /** 读取收藏的仪表盘,重新进入时同步管理页的收藏变化。 */
64
+ async function load() {
65
+ loading.value = true;
66
+ try {
67
+ const config = await defBiCardService.GetBiWorkbench({});
68
+ dashboards.value = orderWorkbenchDashboards(config.dashboard_ids, config.dashboards);
69
+ loaded = true;
70
+ } catch (cause) {
71
+ ElMessage.error(cause instanceof Error ? cause.message : t("bi.query.error"));
72
+ } finally {
73
+ loading.value = false;
74
+ }
75
+ }
76
+ /** 卡片默认允许拖动,按钮保留原有点击操作。 */
77
+ function startDrag(event: DragEvent, index: number) {
78
+ if (saving.value || (event.target as HTMLElement).closest("button")) {
79
+ event.preventDefault();
80
+ return;
81
+ }
82
+ dragged.value = index;
83
+ if (event.dataTransfer) {
84
+ event.dataTransfer.effectAllowed = "move";
85
+ event.dataTransfer.setData("text/plain", String(dashboards.value[index].id));
86
+ }
87
+ }
88
+ /** 拖动或键盘排序后自动保存,失败恢复原顺序并保留卡片收藏。 */
89
+ async function move(from: number, to: number) {
90
+ if (saving.value || from === to || from < 0 || to < 0 || from >= dashboards.value.length || to >= dashboards.value.length)
91
+ return;
92
+ const previous = dashboards.value;
93
+ const next = [...previous];
94
+ const [item] = next.splice(from, 1);
95
+ next.splice(to, 0, item);
96
+ dashboards.value = next;
97
+ dragged.value = -1;
98
+ saving.value = true;
99
+ try {
100
+ const latest = await defBiCardService.GetBiWorkbench({});
101
+ const saved = await defBiCardService.SaveBiWorkbench({
102
+ dashboard_ids: dashboards.value.map(item => item.id),
103
+ favorite_ids: latest.favorite_ids
104
+ });
105
+ dashboards.value = orderWorkbenchDashboards(saved.dashboard_ids, saved.dashboards);
106
+ ElMessage.success(t("bi.workbench.saved"));
107
+ } catch (cause) {
108
+ dashboards.value = previous;
109
+ ElMessage.error(cause instanceof Error ? cause.message : t("bi.query.error"));
110
+ } finally {
111
+ saving.value = false;
112
+ }
113
+ }
114
+ onMounted(() => void load());
115
+ onActivated(() => {
116
+ if (loaded && !saving.value) void load();
117
+ });
118
+ </script>
119
+ <style scoped>
120
+ .bi-workbench {
121
+ container-type: inline-size;
122
+ display: flex;
123
+ flex-direction: column;
124
+ gap: 16px;
125
+ min-width: 0;
126
+ }
127
+ .bi-workbench__grid {
128
+ display: grid;
129
+ grid-template-columns: repeat(4, minmax(0, 1fr));
130
+ gap: 16px;
131
+ }
132
+ .bi-workbench__entry {
133
+ min-width: 0;
134
+ border: 1px solid var(--el-border-color-light);
135
+ border-radius: var(--admin-page-radius);
136
+ overflow: hidden;
137
+ background: var(--admin-page-card-bg);
138
+ cursor: grab;
139
+ }
140
+ .bi-workbench__entry:active {
141
+ cursor: grabbing;
142
+ }
143
+ .bi-workbench__entry:focus-visible {
144
+ outline: 2px solid var(--el-color-primary);
145
+ outline-offset: 2px;
146
+ }
147
+ .bi-workbench__entry.is-dragging {
148
+ border-color: var(--el-color-primary-light-5);
149
+ opacity: 0.5;
150
+ }
151
+ .bi-workbench__info {
152
+ padding: 16px;
153
+ }
154
+ .bi-workbench__title {
155
+ display: flex;
156
+ align-items: flex-start;
157
+ justify-content: space-between;
158
+ gap: 8px;
159
+ }
160
+ .bi-workbench__title .el-tag {
161
+ flex: none;
162
+ }
163
+ .bi-workbench h3 {
164
+ color: var(--el-text-color-primary);
165
+ font-size: 15px;
166
+ font-weight: 500;
167
+ line-height: 22px;
168
+ margin: 0;
169
+ overflow-wrap: anywhere;
170
+ }
171
+ .bi-workbench__meta,
172
+ .bi-workbench__description {
173
+ color: var(--el-text-color-secondary);
174
+ font-size: 12px;
175
+ line-height: 1.6;
176
+ overflow-wrap: anywhere;
177
+ }
178
+ .bi-workbench__meta {
179
+ margin: 6px 0 10px;
180
+ }
181
+ .bi-workbench__description {
182
+ margin: 0 0 10px;
183
+ }
184
+ .bi-workbench footer {
185
+ display: flex;
186
+ justify-content: flex-end;
187
+ flex-wrap: wrap;
188
+ gap: 8px;
189
+ padding-top: 12px;
190
+ margin-top: 12px;
191
+ border-top: 1px solid var(--el-border-color-lighter);
192
+ }
193
+ @container (max-width: 1400px) {
194
+ .bi-workbench__grid {
195
+ grid-template-columns: repeat(3, minmax(0, 1fr));
196
+ }
197
+ }
198
+ @container (max-width: 1050px) {
199
+ .bi-workbench__grid {
200
+ grid-template-columns: repeat(2, minmax(0, 1fr));
201
+ }
202
+ }
203
+ @container (max-width: 650px) {
204
+ .bi-workbench__grid {
205
+ grid-template-columns: 1fr;
206
+ }
207
+ }
208
+ </style>
package/package.json CHANGED
@@ -1,6 +1,70 @@
1
1
  {
2
2
  "name": "@liujitcn/kratos-admin-bi",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "private": false,
4
+ "version": "0.1.6",
5
+ "type": "module",
6
+ "description": "kratos-admin BI analysis and semantic query module",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/liujitcn/kratos-admin",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git@github.com:liujitcn/kratos-admin.git"
12
+ },
13
+ "dependencies": {
14
+ "@vue-flow/background": "^1.3.2",
15
+ "@vue-flow/controls": "^1.1.3",
16
+ "@vue-flow/core": "^1.48.2",
17
+ "@vue-flow/minimap": "^1.5.4",
18
+ "echarts": "^6.1.0",
19
+ "@liujitcn/kratos-admin-system": "0.1.6",
20
+ "@liujitcn/kratos-admin-core": "0.1.6"
21
+ },
22
+ "peerDependencies": {
23
+ "@element-plus/icons-vue": "^2.3.1",
24
+ "@vueuse/core": "^14.3.0",
25
+ "element-plus": "^2.7.6",
26
+ "vue": "^3.5.35",
27
+ "vue-router": "^5.0.7"
28
+ },
29
+ "engines": {
30
+ "node": "^24.0.0"
31
+ },
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/package/declarations/index.d.ts",
35
+ "default": "./dist/package/src/index.ts"
36
+ },
37
+ "./api/*": {
38
+ "types": "./dist/package/declarations/src/api/*.d.ts",
39
+ "default": "./dist/package/src/api/*.ts"
40
+ },
41
+ "./rpc/*": {
42
+ "types": "./dist/package/declarations/src/rpc/*.d.ts",
43
+ "default": "./dist/package/src/rpc/*.ts"
44
+ },
45
+ "./views/*": {
46
+ "types": "./dist/package/declarations/src/views/*.d.ts",
47
+ "default": "./dist/package/src/views/*"
48
+ },
49
+ "./locales/*": "./dist/package/src/locales/*",
50
+ "./module": {
51
+ "types": "./dist/package/declarations/src/module.d.ts",
52
+ "default": "./dist/package/src/module.ts"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "files": [
57
+ "dist/package",
58
+ "package.json",
59
+ "tsconfig.json"
60
+ ],
61
+ "publishConfig": {
62
+ "access": "public"
63
+ },
64
+ "scripts": {
65
+ "build": "pnpm build:package",
66
+ "build:package": "node ../../../scripts/build-package.mjs .",
67
+ "test": "node --test tests/*.test.mjs",
68
+ "type:check": "vue-tsc --noEmit --skipLibCheck"
69
+ }
6
70
  }
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "include": [
4
+ "../../../packages/core/types/generated/auto-imports.d.ts",
5
+ "../../../packages/core/types/generated/components.d.ts",
6
+ "../../../packages/core/src/typings/*.d.ts",
7
+ "src/**/*.ts",
8
+ "src/**/*.d.ts",
9
+ "src/**/*.vue"
10
+ ],
11
+ "exclude": ["node_modules", "dist", "**/*.js"]
12
+ }