@liujitcn/kratos-admin-system 0.0.20 → 0.0.21

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