@liujitcn/kratos-admin-system 0.0.20 → 0.0.23

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 (118) hide show
  1. package/README.md +51 -50
  2. package/dist/package/declarations/src/api/system/base_language.d.ts +52 -0
  3. package/dist/package/declarations/src/api/system/base_translation.d.ts +10 -0
  4. package/dist/package/declarations/src/api/system/code_gen_i18n.d.ts +8 -0
  5. package/dist/package/declarations/src/api/system/ops_monitoring.d.ts +19 -0
  6. package/dist/package/declarations/src/api/system/ops_monitoring_sse.d.ts +12 -0
  7. package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +16 -0
  8. package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +20 -0
  9. package/dist/package/declarations/src/components/dynamicTranslation.d.ts +38 -0
  10. package/dist/package/declarations/src/locales/generated.d.ts +6536 -0
  11. package/dist/package/declarations/src/rpc/base/v1/ai_session.d.ts +12 -2
  12. package/dist/package/declarations/src/rpc/base/v1/ai_tool.d.ts +9 -1
  13. package/dist/package/declarations/src/rpc/base/v1/config.d.ts +35 -0
  14. package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +1 -1
  15. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +23 -2
  16. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +9 -0
  17. package/dist/package/declarations/src/rpc/system/admin/v1/base_job.d.ts +9 -1
  18. package/dist/package/declarations/src/rpc/system/admin/v1/base_language.d.ts +119 -0
  19. package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +6 -1
  20. package/dist/package/declarations/src/rpc/system/admin/v1/base_migration.d.ts +6 -6
  21. package/dist/package/declarations/src/rpc/system/admin/v1/base_role.d.ts +13 -1
  22. package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +75 -0
  23. package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +11 -1
  24. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +13 -11
  25. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_column.d.ts +7 -0
  26. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_table.d.ts +24 -1
  27. package/dist/package/declarations/src/rpc/system/admin/v1/common.d.ts +13 -0
  28. package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +222 -0
  29. package/dist/package/declarations/src/views/base/language/index.vue.d.ts +3 -0
  30. package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue.d.ts +23 -0
  31. package/dist/package/declarations/src/views/tool/code-gen/config.d.ts +7 -7
  32. package/dist/package/declarations/src/views/tool/ops-monitoring/index.vue.d.ts +3 -0
  33. package/dist/package/src/api/base/ai_message.ts +7 -12
  34. package/dist/package/src/api/base/sse.ts +3 -1
  35. package/dist/package/src/api/system/base_language.ts +135 -0
  36. package/dist/package/src/api/system/base_translation.ts +33 -0
  37. package/dist/package/src/api/system/code_gen_column.ts +17 -3
  38. package/dist/package/src/api/system/code_gen_i18n.ts +18 -0
  39. package/dist/package/src/api/system/code_gen_table.ts +12 -4
  40. package/dist/package/src/api/system/ops_monitoring.ts +88 -0
  41. package/dist/package/src/api/system/ops_monitoring_sse.ts +49 -0
  42. package/dist/package/src/components/DynamicTranslationCell.vue +249 -0
  43. package/dist/package/src/components/DynamicTranslationEditor.vue +197 -0
  44. package/dist/package/src/components/dynamicTranslation.ts +66 -0
  45. package/dist/package/src/locales/README.md +30 -0
  46. package/dist/package/src/locales/en-US.json +933 -0
  47. package/dist/package/src/locales/es-ES.json +933 -0
  48. package/dist/package/src/locales/fr-FR.json +933 -0
  49. package/dist/package/src/locales/generated.ts +22 -0
  50. package/dist/package/src/locales/ja-JP.json +933 -0
  51. package/dist/package/src/locales/ko-KR.json +933 -0
  52. package/dist/package/src/locales/zh-CN.json +933 -0
  53. package/dist/package/src/locales/zh-TW.json +933 -0
  54. package/dist/package/src/module.ts +6 -2
  55. package/dist/package/src/rpc/base/v1/ai_session.ts +13 -2
  56. package/dist/package/src/rpc/base/v1/ai_tool.ts +10 -1
  57. package/dist/package/src/rpc/base/v1/config.ts +47 -0
  58. package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
  59. package/dist/package/src/rpc/system/admin/v1/base_config.ts +24 -2
  60. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +9 -0
  61. package/dist/package/src/rpc/system/admin/v1/base_job.ts +10 -1
  62. package/dist/package/src/rpc/system/admin/v1/base_language.ts +141 -0
  63. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +6 -1
  64. package/dist/package/src/rpc/system/admin/v1/base_migration.ts +8 -8
  65. package/dist/package/src/rpc/system/admin/v1/base_role.ts +14 -1
  66. package/dist/package/src/rpc/system/admin/v1/base_translation.ts +90 -0
  67. package/dist/package/src/rpc/system/admin/v1/base_user.ts +12 -1
  68. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +16 -12
  69. package/dist/package/src/rpc/system/admin/v1/code_gen_column.ts +8 -0
  70. package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +27 -1
  71. package/dist/package/src/rpc/system/admin/v1/common.ts +21 -0
  72. package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +255 -0
  73. package/dist/package/src/views/ai/chat/components/AiMarkdown.vue +1 -6
  74. package/dist/package/src/views/ai/chat/components/ChatPanel.vue +75 -58
  75. package/dist/package/src/views/ai/chat/components/SessionPanel.vue +20 -9
  76. package/dist/package/src/views/ai/chat/components/XSender.vue +36 -23
  77. package/dist/package/src/views/ai/chat/index.vue +58 -41
  78. package/dist/package/src/views/ai/chat/message.ts +29 -27
  79. package/dist/package/src/views/base/api/index.vue +121 -84
  80. package/dist/package/src/views/base/area/index.vue +81 -32
  81. package/dist/package/src/views/base/config/index.vue +300 -96
  82. package/dist/package/src/views/base/dept/index.vue +110 -62
  83. package/dist/package/src/views/base/dict/index.vue +145 -62
  84. package/dist/package/src/views/base/dict/item.vue +155 -64
  85. package/dist/package/src/views/base/job/index.vue +134 -82
  86. package/dist/package/src/views/base/job/log.vue +24 -25
  87. package/dist/package/src/views/base/language/index.vue +260 -0
  88. package/dist/package/src/views/base/log/index.vue +68 -46
  89. package/dist/package/src/views/base/menu/index.vue +344 -200
  90. package/dist/package/src/views/base/migration/index.vue +49 -29
  91. package/dist/package/src/views/base/post/index.vue +128 -60
  92. package/dist/package/src/views/base/role/index.vue +145 -79
  93. package/dist/package/src/views/base/tenant/index.vue +132 -64
  94. package/dist/package/src/views/base/user/components/dept-tree.vue +2 -1
  95. package/dist/package/src/views/base/user/index.vue +194 -116
  96. package/dist/package/src/views/profile/components/base.vue +45 -28
  97. package/dist/package/src/views/profile/components/password.vue +45 -30
  98. package/dist/package/src/views/profile/components/security.vue +90 -54
  99. package/dist/package/src/views/profile/index.vue +10 -9
  100. package/dist/package/src/views/tool/api-doc/index.vue +6 -2
  101. package/dist/package/src/views/tool/code-gen/code-preview/index.vue +32 -16
  102. package/dist/package/src/views/tool/code-gen/columns/index.vue +382 -273
  103. package/dist/package/src/views/tool/code-gen/columns/option-copy.ts +1 -6
  104. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +118 -0
  105. package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +65 -36
  106. package/dist/package/src/views/tool/code-gen/components/CodePreviewPane.vue +8 -5
  107. package/dist/package/src/views/tool/code-gen/config.ts +116 -79
  108. package/dist/package/src/views/tool/code-gen/preview/data.ts +19 -17
  109. package/dist/package/src/views/tool/code-gen/preview/index.vue +96 -59
  110. package/dist/package/src/views/tool/code-gen/proto/index.vue +110 -62
  111. package/dist/package/src/views/tool/code-gen/table/index.vue +201 -121
  112. package/dist/package/src/views/tool/ops-monitoring/index.vue +1175 -0
  113. package/dist/package/src/views/tool/project-doc/index.vue +17 -15
  114. package/package.json +6 -2
  115. package/dist/package/declarations/src/rpc/base/v1/enum.d.ts +0 -43
  116. package/dist/package/declarations/src/rpc/system/common/v1/enum.d.ts +0 -67
  117. package/dist/package/src/rpc/base/v1/enum.ts +0 -54
  118. package/dist/package/src/rpc/system/common/v1/enum.ts +0 -80
@@ -1,7 +1,12 @@
1
1
  import previewAvatar from "@liujitcn/kratos-admin-core/assets/images/avatar.png";
2
+ import { t } from "@liujitcn/kratos-admin-core";
2
3
  import type { ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
3
4
  import type { OptionBaseDictResponse_BaseDict } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_dict";
4
- import type { CodeGenColumn, CodeGenColumnOptionConfig, CodeGenColumnQueryConfig } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_column";
5
+ import type {
6
+ CodeGenColumn,
7
+ CodeGenColumnOptionConfig,
8
+ CodeGenColumnQueryConfig
9
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_column";
5
10
  import type { CodeGenLeftTreeConfig, CodeGenTableForm } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_table";
6
11
 
7
12
  /** 页面预览中的字段配置范围。 */
@@ -79,7 +84,7 @@ export function createCodeGenLeftTreeOptions(config?: CodeGenLeftTreeConfig): Pr
79
84
  inactive_value: "",
80
85
  lazy: config.lazy
81
86
  };
82
- return createCodeGenPreviewOptions(config.label_column || "分类", option, new Map());
87
+ return createCodeGenPreviewOptions(config.label_column || t("system.code.gen.preview.value.category"), option, new Map());
83
88
  }
84
89
 
85
90
  /** 创建页面列表所需的模拟业务记录。 */
@@ -91,21 +96,18 @@ export function createCodeGenPreviewRows(
91
96
  const { table, columns } = snapshot;
92
97
  const primaryColumn = resolveCodeGenPrimaryColumn(columns);
93
98
  const leftTreeValues = flattenCodeGenPreviewOptions(leftTreeOptions).map(option => option.value);
94
- const rows = Array.from(
95
- { length: table.page_type === "tree" || table.page_type === "tree_lazy" ? 12 : 18 },
96
- (_, rowIndex) => {
97
- const row: CodeGenPreviewRow = {};
98
- columns.forEach(column => {
99
- const options = resolveColumnPreviewOptions(optionMap, column);
100
- row[column.name] = createCodeGenPreviewValue(column, rowIndex, options);
101
- });
102
- if (!(primaryColumn in row)) row[primaryColumn] = rowIndex + 1;
103
- if (table.page_type === "left_tree" && table.left_tree_config?.filter_column && leftTreeValues.length) {
104
- row[table.left_tree_config.filter_column] = leftTreeValues[rowIndex % leftTreeValues.length];
105
- }
106
- return row;
99
+ const rows = Array.from({ length: table.page_type === "tree" || table.page_type === "tree_lazy" ? 12 : 18 }, (_, rowIndex) => {
100
+ const row: CodeGenPreviewRow = {};
101
+ columns.forEach(column => {
102
+ const options = resolveColumnPreviewOptions(optionMap, column);
103
+ row[column.name] = createCodeGenPreviewValue(column, rowIndex, options);
104
+ });
105
+ if (!(primaryColumn in row)) row[primaryColumn] = rowIndex + 1;
106
+ if (table.page_type === "left_tree" && table.left_tree_config?.filter_column && leftTreeValues.length) {
107
+ row[table.left_tree_config.filter_column] = leftTreeValues[rowIndex % leftTreeValues.length];
107
108
  }
108
- );
109
+ return row;
110
+ });
109
111
 
110
112
  // 树形页面按照真实父节点字段构造层级,列表字段和值仍来自当前数据库配置。
111
113
  if (
@@ -215,7 +217,7 @@ function createCodeGenPreviewOptions(
215
217
  });
216
218
  }
217
219
  return Array.from({ length: 4 }, (_, optionIndex) => ({
218
- label: `${sourceLabel}选项 ${optionIndex + 1}`,
220
+ label: t("system.code.gen.preview.value.option", { source: sourceLabel, index: optionIndex + 1 }),
219
221
  value: `${sourceLabel}-${optionIndex + 1}`
220
222
  }));
221
223
  }
@@ -53,12 +53,11 @@
53
53
  <FormDialog
54
54
  v-model="dialog.visible"
55
55
  ref="formDialogRef"
56
- :title="dialog.title"
56
+ :title="dialogTitle"
57
57
  width="min(920px, calc(100vw - 32px))"
58
58
  top="4vh"
59
59
  :model="previewFormModel"
60
60
  :fields="formFields"
61
- label-width="116px"
62
61
  :gutter="20"
63
62
  :col-span="12"
64
63
  @confirm="handleSubmit"
@@ -68,13 +67,13 @@
68
67
  <PasswordStrength :password="String(previewFormModel[passwordFieldName])" />
69
68
  </template>
70
69
  <template #codeGenPreviewSlot="{ field }">
71
- <el-input v-model="previewFormModel[field.prop]" placeholder="自定义插槽内容">
72
- <template #append>自定义</template>
70
+ <el-input v-model="previewFormModel[field.prop]" :placeholder="t('system.code.gen.preview.placeholder.custom_slot')">
71
+ <template #append>{{ t("system.code.gen.preview.value.custom") }}</template>
73
72
  </el-input>
74
73
  </template>
75
74
  </FormDialog>
76
75
  </template>
77
- <el-empty v-else-if="!loading" description="暂无页面配置" />
76
+ <el-empty v-else-if="!loading" :description="t('system.code.gen.preview.message.empty_page')" />
78
77
  </div>
79
78
  </template>
80
79
 
@@ -83,8 +82,14 @@ import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
83
82
  import { ElMessage, ElMessageBox } from "element-plus";
84
83
  import { CirclePlus, Delete, EditPen } from "@element-plus/icons-vue";
85
84
  import { useRoute } from "vue-router";
85
+ import { t } from "@liujitcn/kratos-admin-core";
86
86
  import ProTable from "@liujitcn/kratos-admin-core/components/ProTable";
87
- import type { ColumnProps, HeaderActionProps, ProTableInstance, RenderScope } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
87
+ import type {
88
+ ColumnProps,
89
+ HeaderActionProps,
90
+ ProTableInstance,
91
+ RenderScope
92
+ } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
88
93
  import FormDialog from "@liujitcn/kratos-admin-core/components/Dialog/FormDialog.vue";
89
94
  import PasswordStrength from "@liujitcn/kratos-admin-core/components/PasswordStrength/index.vue";
90
95
  import type { ProFormComponentType, ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
@@ -132,14 +137,23 @@ const mockRows = ref<CodeGenPreviewRow[]>([]);
132
137
  const previewFormModel = reactive<Record<string, any>>({});
133
138
  const editingRowKey = ref<string | number>();
134
139
  const selectedLeftTreeValues = ref<Array<string | number | boolean>>([]);
135
- const passwordFieldName = computed(() => snapshot.value?.columns.find(column => column.form_config?.component === "password")?.name ?? "pwd");
136
- const supportedFormComponents = new Set(codeGenFormComponentOptions.map(item => String(item.value)));
140
+ const passwordFieldName = computed(
141
+ () => snapshot.value?.columns.find(column => column.form_config?.component === "password")?.name ?? "pwd"
142
+ );
143
+ const supportedFormComponents = computed(() => new Set(codeGenFormComponentOptions().map(item => String(item.value))));
137
144
 
138
145
  const dialog = reactive({
139
- title: "",
146
+ editing: false,
140
147
  visible: false
141
148
  });
142
149
 
150
+ /** 模拟数据新增或编辑弹窗标题。 */
151
+ const dialogTitle = computed(() =>
152
+ t(dialog.editing ? "system.code.gen.preview.title.edit" : "system.code.gen.preview.title.create", {
153
+ resource: snapshot.value?.table.comment || t("system.code.gen.preview.value.data")
154
+ })
155
+ );
156
+
143
157
  /** 当前代码生成表配置 ID。 */
144
158
  const tableId = computed(() => {
145
159
  const value = route.params.tableId;
@@ -180,7 +194,7 @@ const leftTreeTitle = computed(
180
194
  snapshot.value?.table.left_tree_config?.comment ||
181
195
  leftTreeTableComment.value ||
182
196
  snapshot.value?.table.left_tree_config?.table_name ||
183
- "分类列表"
197
+ t("system.code.gen.preview.title.category_list")
184
198
  );
185
199
 
186
200
  /** 当前实体已经存在或已经选择生成的 Proto 维护能力。 */
@@ -192,7 +206,8 @@ const protoCapabilities = computed(() =>
192
206
  const tableColumns = computed<ColumnProps[]>(() => {
193
207
  const columns = snapshot.value?.columns ?? [];
194
208
  const treeParentColumn = pageType.value === "tree" || pageType.value === "tree_lazy" ? snapshot.value?.table.parent_column : "";
195
- const treeLabelColumn = pageType.value === "tree" || pageType.value === "tree_lazy" ? snapshot.value?.table.tree_label_column : "";
209
+ const treeLabelColumn =
210
+ pageType.value === "tree" || pageType.value === "tree_lazy" ? snapshot.value?.table.tree_label_column : "";
196
211
  const configuredColumns = columns
197
212
  .filter(
198
213
  column =>
@@ -212,9 +227,8 @@ const tableColumns = computed<ColumnProps[]>(() => {
212
227
  const isTreeLabel = column.name === treeLabelColumn;
213
228
  const isTreeParent = column.name === treeParentColumn && treeParentColumn !== treeLabelColumn;
214
229
  const listConfig = column.list_config ?? { enabled: false, component: "input", option: undefined };
215
- const previewColumn = isTreeLabel && !listConfig.enabled
216
- ? { ...column, list_config: { ...listConfig, enabled: true } }
217
- : column;
230
+ const previewColumn =
231
+ isTreeLabel && !listConfig.enabled ? { ...column, list_config: { ...listConfig, enabled: true } } : column;
218
232
  const result = createPreviewTableColumn(previewColumn);
219
233
  if (isTreeLabel) result.align = "left";
220
234
  if (isTreeParent) {
@@ -228,7 +242,7 @@ const tableColumns = computed<ColumnProps[]>(() => {
228
242
  const actions: NonNullable<ColumnProps["actions"]> = [];
229
243
  if (protoCapabilities.value.update) {
230
244
  actions.push({
231
- label: "编辑",
245
+ label: t("common.action.edit"),
232
246
  type: "primary",
233
247
  link: true,
234
248
  icon: EditPen,
@@ -237,7 +251,7 @@ const tableColumns = computed<ColumnProps[]>(() => {
237
251
  }
238
252
  if (protoCapabilities.value.delete) {
239
253
  actions.push({
240
- label: "删除",
254
+ label: t("common.action.delete"),
241
255
  type: "danger",
242
256
  link: true,
243
257
  icon: Delete,
@@ -247,7 +261,7 @@ const tableColumns = computed<ColumnProps[]>(() => {
247
261
  if (actions.length) {
248
262
  result.push({
249
263
  prop: "operation",
250
- label: "操作",
264
+ label: t("common.field.operation"),
251
265
  width: actions.length === 1 ? 100 : 180,
252
266
  fixed: "right",
253
267
  cellType: "actions",
@@ -262,7 +276,7 @@ const headerActions = computed<HeaderActionProps[]>(() => {
262
276
  const actions: HeaderActionProps[] = [];
263
277
  if (protoCapabilities.value.create && formFields.value.length) {
264
278
  actions.push({
265
- label: "新增",
279
+ label: t("common.action.create"),
266
280
  type: "success",
267
281
  icon: CirclePlus,
268
282
  onClick: () => handleOpenDialog()
@@ -270,7 +284,7 @@ const headerActions = computed<HeaderActionProps[]>(() => {
270
284
  }
271
285
  if (protoCapabilities.value.delete) {
272
286
  actions.push({
273
- label: "删除",
287
+ label: t("common.action.delete"),
274
288
  type: "danger",
275
289
  icon: Delete,
276
290
  disabled: scope => !scope.selectedList.length,
@@ -284,8 +298,7 @@ const headerActions = computed<HeaderActionProps[]>(() => {
284
298
  const formFields = computed<ProFormField[]>(() => {
285
299
  return (snapshot.value?.columns ?? [])
286
300
  .filter(
287
- column =>
288
- !column.is_primary && !column.is_auto_increment && column.name !== "deleted_at" && column.form_config?.enabled
301
+ column => !column.is_primary && !column.is_auto_increment && column.name !== "deleted_at" && column.form_config?.enabled
289
302
  )
290
303
  .sort((left, right) => left.sort - right.sort)
291
304
  .flatMap(column => {
@@ -294,9 +307,7 @@ const formFields = computed<ProFormField[]>(() => {
294
307
  (pageType.value === "tree" || pageType.value === "tree_lazy") && column.name === snapshot.value?.table.parent_column;
295
308
  const component = isTreeParent ? "tree-select" : resolvePreviewFormComponent(column.form_config?.component);
296
309
  const isMultipleTreeSelect = component === "tree-select" && Boolean(column.form_config?.multiple);
297
- const options = isTreeParent
298
- ? treeParentOptions.value
299
- : resolveCodeGenPreviewOptions(optionMap.value, column.name, "form");
310
+ const options = isTreeParent ? treeParentOptions.value : resolveCodeGenPreviewOptions(optionMap.value, column.name, "form");
300
311
  const field: ProFormField = {
301
312
  prop: column.name,
302
313
  label,
@@ -306,10 +317,12 @@ const formFields = computed<ProFormField[]>(() => {
306
317
  ...(isTreeParent ? { disabled: Boolean(previewFormModel[primaryColumn.value]) } : {})
307
318
  },
308
319
  options,
309
- checkboxLabel: component === "checkbox" ? `启用${label}` : undefined,
320
+ checkboxLabel: component === "checkbox" ? t("system.code.gen.preview.value.enable_field", { field: label }) : undefined,
310
321
  slotName: component === "slot" ? "codeGenPreviewSlot" : undefined,
311
322
  visible: component === "password" ? model => !model[primaryColumn.value] : undefined,
312
- rules: column.form_config?.required ? [{ required: true, message: `${label}不能为空` }] : undefined,
323
+ rules: column.form_config?.required
324
+ ? [{ required: true, message: t("system.code.gen.preview.validation.required", { field: label }) }]
325
+ : undefined,
313
326
  colSpan: resolvePreviewColSpan(component)
314
327
  };
315
328
  if (component !== "password") return [field];
@@ -317,7 +330,7 @@ const formFields = computed<ProFormField[]>(() => {
317
330
  field,
318
331
  {
319
332
  prop: "passwordStrength",
320
- label: "强度提示",
333
+ label: t("system.code.gen.preview.field.password_strength"),
321
334
  component: "slot",
322
335
  slotName: "passwordStrength",
323
336
  visible: model => !model[primaryColumn.value]
@@ -330,7 +343,7 @@ const formFields = computed<ProFormField[]>(() => {
330
343
  const treeParentOptions = computed<ProFormOption[]>(() => {
331
344
  if (!snapshot.value?.table.parent_column || (pageType.value !== "tree" && pageType.value !== "tree_lazy")) return [];
332
345
  const treeRows = buildCodeGenPreviewTree(mockRows.value, primaryColumn.value, snapshot.value.table.parent_column);
333
- return [{ label: "顶级节点", value: 0 }, ...mapPreviewRowsToOptions(treeRows)];
346
+ return [{ label: t("system.code.gen.preview.value.top_level"), value: 0 }, ...mapPreviewRowsToOptions(treeRows)];
334
347
  });
335
348
 
336
349
  // 路由生成对象变化时重新载入对应预览。
@@ -393,11 +406,7 @@ async function requestPreviewTable(params: Record<string, any>) {
393
406
  }
394
407
 
395
408
  /** 请求懒加载树表格的子节点。 */
396
- async function loadPreviewTreeChildren(
397
- row: CodeGenPreviewRow,
398
- _treeNode: unknown,
399
- resolve: (data: CodeGenPreviewRow[]) => void
400
- ) {
409
+ async function loadPreviewTreeChildren(row: CodeGenPreviewRow, _treeNode: unknown, resolve: (data: CodeGenPreviewRow[]) => void) {
401
410
  const parentColumn = snapshot.value?.table.parent_column;
402
411
  if (!parentColumn) {
403
412
  resolve([]);
@@ -442,9 +451,7 @@ async function loadPreview() {
442
451
  /** 根据 TreeFilter 当前节点筛选该节点及其全部子节点。 */
443
452
  function handleLeftTreeChange(value: string | number | boolean | undefined) {
444
453
  const selectedNode = flattenCodeGenPreviewOptions(leftTreeOptions.value).find(option => String(option.value) === String(value));
445
- selectedLeftTreeValues.value = selectedNode
446
- ? flattenCodeGenPreviewOptions([selectedNode]).map(option => option.value)
447
- : [];
454
+ selectedLeftTreeValues.value = selectedNode ? flattenCodeGenPreviewOptions([selectedNode]).map(option => option.value) : [];
448
455
  proTable.value?.search();
449
456
  }
450
457
 
@@ -452,7 +459,7 @@ function handleLeftTreeChange(value: string | number | boolean | undefined) {
452
459
  function handleOpenDialog(row?: CodeGenPreviewRow) {
453
460
  resetPreviewForm(row);
454
461
  editingRowKey.value = row?.[primaryColumn.value];
455
- dialog.title = row ? `编辑${snapshot.value?.table.comment || "数据"}` : `新增${snapshot.value?.table.comment || "数据"}`;
462
+ dialog.editing = Boolean(row);
456
463
  dialog.visible = true;
457
464
  }
458
465
 
@@ -493,7 +500,11 @@ function handleSubmit() {
493
500
  }
494
501
  mockRows.value.unshift(newRow);
495
502
  }
496
- const successMessage = editingRowKey.value !== undefined ? "修改成功" : "新增成功";
503
+ const successMessage = t(
504
+ editingRowKey.value !== undefined
505
+ ? "system.code.gen.preview.message.update_success"
506
+ : "system.code.gen.preview.message.create_success"
507
+ );
497
508
  handleCloseDialog();
498
509
  await nextTick();
499
510
  refreshTable();
@@ -504,15 +515,19 @@ function handleSubmit() {
504
515
  /** 删除一条或多条模拟记录。 */
505
516
  async function handleDelete(rows: CodeGenPreviewRow[]) {
506
517
  if (!rows.length) {
507
- ElMessage.warning("请勾选删除项");
518
+ ElMessage.warning(t("common.message.select_delete_item"));
508
519
  return;
509
520
  }
510
521
  try {
511
- await ElMessageBox.confirm(`确认删除选中的 ${rows.length} 条数据吗?`, "删除确认", {
512
- confirmButtonText: "确定",
513
- cancelButtonText: "取消",
514
- type: "warning"
515
- });
522
+ await ElMessageBox.confirm(
523
+ t("system.code.gen.preview.dialog.confirm_delete", { count: rows.length }),
524
+ t("system.code.gen.preview.title.delete_confirm"),
525
+ {
526
+ confirmButtonText: t("common.action.confirm"),
527
+ cancelButtonText: t("common.action.cancel"),
528
+ type: "warning"
529
+ }
530
+ );
516
531
  } catch {
517
532
  return;
518
533
  }
@@ -520,7 +535,7 @@ async function handleDelete(rows: CodeGenPreviewRow[]) {
520
535
  mockRows.value = mockRows.value.filter(row => !keys.has(String(row[primaryColumn.value])));
521
536
  await nextTick();
522
537
  refreshTable();
523
- ElMessage.success("删除成功");
538
+ ElMessage.success(t("system.code.gen.preview.message.delete_success"));
524
539
  }
525
540
 
526
541
  /** 创建当前页面类型使用的完整模拟数据。 */
@@ -531,7 +546,7 @@ function createMockRows() {
531
546
 
532
547
  /** 同步预览页签和浏览器标题。 */
533
548
  function syncWorkspaceTitle() {
534
- const title = snapshot.value?.table.comment || snapshot.value?.table.name || "数据列表";
549
+ const title = snapshot.value?.table.comment || snapshot.value?.table.name || t("system.code.gen.preview.title.data_list");
535
550
  tabsStore.setTabsTitle(title);
536
551
  document.title = `${title} - ${import.meta.env.VITE_GLOB_APP_TITLE}`;
537
552
  }
@@ -658,7 +673,7 @@ function mapPreviewRowsToOptions(rows: CodeGenPreviewRow[], parentPath = ""): Pr
658
673
  /** 将配置中的组件字符串收敛为 ProForm 支持类型,字典预览使用模拟下拉避免接口请求。 */
659
674
  function resolvePreviewFormComponent(component?: string): ProFormComponentType {
660
675
  if (component === "dict") return "select";
661
- return component && supportedFormComponents.has(component) ? (component as ProFormComponentType) : "input";
676
+ return component && supportedFormComponents.value.has(component) ? (component as ProFormComponentType) : "input";
662
677
  }
663
678
 
664
679
  /** 创建不同 ProForm 组件在最终新增弹窗中的参数。 */
@@ -671,20 +686,35 @@ function createPreviewFormProps(
671
686
  const fullWidthStyle = { width: "100%" };
672
687
  switch (component) {
673
688
  case "input":
674
- return { placeholder: `请输入${label}`, clearable: true, style: fullWidthStyle };
689
+ return {
690
+ placeholder: t("system.code.gen.preview.placeholder.input", { field: label }),
691
+ clearable: true,
692
+ style: fullWidthStyle
693
+ };
675
694
  case "password":
676
- return { placeholder: `请输入${label}`, clearable: true, showPassword: true, style: fullWidthStyle };
695
+ return {
696
+ placeholder: t("system.code.gen.preview.placeholder.input", { field: label }),
697
+ clearable: true,
698
+ showPassword: true,
699
+ style: fullWidthStyle
700
+ };
677
701
  case "textarea":
678
- return { placeholder: `请输入${label}`, rows: 4 };
702
+ return { placeholder: t("system.code.gen.preview.placeholder.input", { field: label }), rows: 4 };
679
703
  case "input-number":
680
704
  return { min: 0, controlsPosition: "right", style: fullWidthStyle };
681
705
  case "segmented":
682
706
  return { block: true };
683
707
  case "select":
684
- return { placeholder: `请选择${label}`, clearable: true, filterable: true, checkStrictly: true, style: fullWidthStyle };
708
+ return {
709
+ placeholder: t("system.code.gen.preview.placeholder.select", { field: label }),
710
+ clearable: true,
711
+ filterable: true,
712
+ checkStrictly: true,
713
+ style: fullWidthStyle
714
+ };
685
715
  case "tree-select":
686
716
  return {
687
- placeholder: `请选择${label}`,
717
+ placeholder: t("system.code.gen.preview.placeholder.select", { field: label }),
688
718
  clearable: true,
689
719
  filterable: true,
690
720
  checkStrictly: true,
@@ -692,18 +722,25 @@ function createPreviewFormProps(
692
722
  style: fullWidthStyle
693
723
  };
694
724
  case "date-picker":
695
- return { type: "datetime", placeholder: `请选择${label}`, style: fullWidthStyle };
725
+ return {
726
+ type: "datetime",
727
+ placeholder: t("system.code.gen.preview.placeholder.select", { field: label }),
728
+ style: fullWidthStyle
729
+ };
696
730
  case "transfer":
697
- return { titles: ["可选项", "已选项"] };
731
+ return { titles: [t("system.code.gen.preview.value.available"), t("system.code.gen.preview.value.selected")] };
698
732
  case "image-upload":
699
733
  case "images-upload":
700
734
  case "file-upload":
701
735
  case "files-upload":
702
736
  return { disabled: true };
703
737
  case "dynamic-list":
704
- return { inputProps: { placeholder: `请输入${label}` } };
738
+ return { inputProps: { placeholder: t("system.code.gen.preview.placeholder.input", { field: label }) } };
705
739
  case "kv-list":
706
- return { keyInputProps: { placeholder: "键" }, valueInputProps: { placeholder: "值" } };
740
+ return {
741
+ keyInputProps: { placeholder: t("system.code.gen.preview.value.key") },
742
+ valueInputProps: { placeholder: t("system.code.gen.preview.value.value") }
743
+ };
707
744
  default:
708
745
  return option?.source_value ? { placeholder: option.source_value } : {};
709
746
  }
@@ -720,9 +757,9 @@ function createPreviewSearchProps(column: CodeGenColumn) {
720
757
  const props: Record<string, any> = { clearable: true, style: { width: "100%" } };
721
758
  if (column.query_config?.component === "date-picker") {
722
759
  props.type = column.query_config.operator === "between" ? "datetimerange" : "datetime";
723
- props.rangeSeparator = "至";
724
- props.startPlaceholder = "开始时间";
725
- props.endPlaceholder = "结束时间";
760
+ props.rangeSeparator = t("system.code.gen.preview.value.range_separator");
761
+ props.startPlaceholder = t("common.placeholder.start_date");
762
+ props.endPlaceholder = t("common.placeholder.end_date");
726
763
  }
727
764
  if (column.query_config?.component === "tree-select") {
728
765
  props.checkStrictly = true;