@liujitcn/kratos-admin-system 0.0.19 → 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
@@ -12,7 +12,7 @@
12
12
  <FormDialog
13
13
  v-model="dialog.visible"
14
14
  ref="formDialogRef"
15
- :title="dialog.title"
15
+ :title="t(dialog.titleKey, { resource: t('system.config.resource') })"
16
16
  width="1200px"
17
17
  :model="formData"
18
18
  :fields="formFields"
@@ -22,7 +22,10 @@
22
22
  @close="handleCloseDialog"
23
23
  >
24
24
  <template #textValue>
25
- <el-input v-model="formData.value" placeholder="请输入配置值" />
25
+ <el-input
26
+ v-model="formData.value"
27
+ :placeholder="t('system.common.validation.requiredInput', { field: t('system.config.field.value') })"
28
+ />
26
29
  </template>
27
30
  <template #imageValue>
28
31
  <UploadImg v-model:image-url="formData.value" upload-type="config" />
@@ -31,8 +34,18 @@
31
34
  <WangEditor v-model:value="formData.value" />
32
35
  </template>
33
36
  <template #dictValue>
34
- <Dict v-if="dictValueCode" v-model="formData.value" :code="dictValueCode" code-type="string" placeholder="请选择字典配置值" />
35
- <el-input v-else v-model="formData.value" placeholder="请输入配置值" />
37
+ <Dict
38
+ v-if="dictValueCode"
39
+ v-model="formData.value"
40
+ :code="dictValueCode"
41
+ code-type="string"
42
+ :placeholder="t('system.common.validation.requiredSelect', { field: t('system.config.field.value') })"
43
+ />
44
+ <el-input
45
+ v-else
46
+ v-model="formData.value"
47
+ :placeholder="t('system.common.validation.requiredInput', { field: t('system.config.field.value') })"
48
+ />
36
49
  </template>
37
50
  <template #booleanValue>
38
51
  <el-switch
@@ -44,6 +57,27 @@
44
57
  inline-prompt
45
58
  />
46
59
  </template>
60
+ <template #nameTranslations>
61
+ <DynamicTranslationEditor
62
+ v-model="nameTranslationValues"
63
+ :resource-id="formData.id"
64
+ :resource-type="TranslationResourceType.TRANSLATION_RESOURCE_TYPE_CONFIG"
65
+ :field="BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_NAME"
66
+ :draft-enabled="configStore.translationDraftEnabled"
67
+ :maxlength="100"
68
+ />
69
+ </template>
70
+ <template #valueTranslations>
71
+ <DynamicTranslationEditor
72
+ v-model="valueTranslationValues"
73
+ :resource-id="formData.id"
74
+ :resource-type="TranslationResourceType.TRANSLATION_RESOURCE_TYPE_CONFIG"
75
+ :field="BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_VALUE"
76
+ :draft-enabled="configStore.translationDraftEnabled"
77
+ :maxlength="10000"
78
+ multiline
79
+ />
80
+ </template>
47
81
  </FormDialog>
48
82
  </div>
49
83
  </template>
@@ -62,11 +96,27 @@ import UploadImg from "@liujitcn/kratos-admin-core/components/Upload/Img.vue";
62
96
  import WangEditor from "@liujitcn/kratos-admin-core/components/WangEditor/index.vue";
63
97
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
64
98
  import { defBaseConfigService } from "@liujitcn/kratos-admin-system/api/system/base_config";
65
- import type { BaseConfig, BaseConfigForm, PageBaseConfigRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_config";
99
+ import { loadEnabledBaseLanguages } from "@liujitcn/kratos-admin-system/api/system/base_language";
100
+ import type {
101
+ BaseConfig,
102
+ BaseConfigForm,
103
+ PageBaseConfigRequest
104
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_config";
105
+ import type { BaseConfigTranslation } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_translation";
66
106
  import { BaseConfigSite } from "@liujitcn/kratos-admin-system/rpc/base/v1/enum";
67
107
  import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
68
108
  import { BaseConfigType } from "@liujitcn/kratos-admin-system/rpc/system/common/v1/enum";
69
109
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
110
+ import { t } from "@liujitcn/kratos-admin-core";
111
+ import { useConfigStore } from "@liujitcn/kratos-admin-core/stores/runtime";
112
+ import DynamicTranslationEditor from "@liujitcn/kratos-admin-system/components/DynamicTranslationEditor.vue";
113
+ import DynamicTranslationCell from "@liujitcn/kratos-admin-system/components/DynamicTranslationCell.vue";
114
+ import { getEditableLanguageOptions, type DynamicTranslationValue } from "@liujitcn/kratos-admin-system/components/dynamicTranslation";
115
+ import {
116
+ BaseConfigTranslationField,
117
+ TranslationResourceType,
118
+ TranslationStatus
119
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_translation";
70
120
 
71
121
  defineOptions({
72
122
  name: "BaseConfig",
@@ -74,11 +124,12 @@ defineOptions({
74
124
  });
75
125
 
76
126
  const { BUTTONS } = useAuthButtons();
127
+ const configStore = useConfigStore();
77
128
  const proTable = ref<ProTableInstance>();
78
129
  const formDialogRef = ref<InstanceType<typeof FormDialog>>();
79
130
 
80
131
  const dialog = reactive({
81
- title: "",
132
+ titleKey: "system.common.action.createResource",
82
133
  visible: false
83
134
  });
84
135
 
@@ -96,28 +147,118 @@ const formData = reactive<BaseConfigForm>({
96
147
  /** 配置value */
97
148
  value: "",
98
149
  /** 状态 */
99
- status: Status.ENABLE
150
+ status: Status.ENABLE,
151
+ /** 配置全部非主语言翻译。 */
152
+ translations: []
100
153
  });
101
154
 
102
- const rules = reactive({
103
- site: [{ required: true, message: "请选择系统配置位置", trigger: "change" }],
155
+ /** 将配置翻译记录转换为编辑器值,缺少记录时保留可编辑的空行。 */
156
+ function normalizeConfigTranslations(field: BaseConfigTranslationField): DynamicTranslationValue[] {
157
+ return getEditableLanguageOptions().map(item => item.value).map(locale => {
158
+ const record = formData.translations?.find(item => item.locale === locale && item.field === field);
159
+ return {
160
+ id: record?.id ?? 0,
161
+ locale,
162
+ text: record?.text ?? "",
163
+ translation_status: record?.translation_status ?? TranslationStatus.TRANSLATION_STATUS_PENDING,
164
+ source_changed: record?.source_changed ?? false,
165
+ source_hash: record?.source_hash ?? "",
166
+ translation_provider: record?.translation_provider ?? "",
167
+ translated_at: record?.translated_at ?? "",
168
+ reviewed_by: record?.reviewed_by ?? 0,
169
+ reviewed_at: record?.reviewed_at ?? "",
170
+ created_by: record?.created_by ?? 0,
171
+ updated_by: record?.updated_by ?? 0,
172
+ created_at: record?.created_at ?? "",
173
+ updated_at: record?.updated_at ?? "",
174
+ deleted_at: record?.deleted_at ?? 0
175
+ };
176
+ });
177
+ }
178
+
179
+ /** 保存指定字段的编辑器值,并保留另一字段的翻译。 */
180
+ function updateConfigTranslations(field: BaseConfigTranslationField, values: DynamicTranslationValue[]) {
181
+ const remaining = (formData.translations ?? []).filter(item => item.field !== field);
182
+ const next = values.map(item =>
183
+ ({
184
+ ...item,
185
+ config_id: formData.id,
186
+ field,
187
+ text: item.text
188
+ }) as BaseConfigTranslation
189
+ );
190
+ formData.translations = [...remaining, ...next];
191
+ }
192
+
193
+ const nameTranslationValues = computed<DynamicTranslationValue[]>({
194
+ get: () => normalizeConfigTranslations(BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_NAME),
195
+ set: values => updateConfigTranslations(BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_NAME, values)
196
+ });
197
+
198
+ const valueTranslationValues = computed<DynamicTranslationValue[]>({
199
+ get: () => normalizeConfigTranslations(BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_VALUE),
200
+ set: values => updateConfigTranslations(BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_VALUE, values)
201
+ });
202
+
203
+ const rules = computed(() => ({
204
+ site: [
205
+ {
206
+ required: true,
207
+ message: t("system.common.validation.requiredSelect", { field: t("system.config.field.site") }),
208
+ trigger: "change"
209
+ }
210
+ ],
104
211
  name: [
105
- { required: true, message: "请输入系统配置名称", trigger: "blur" },
106
- { max: 50, message: "配置名称不能超过 50 个字符", trigger: "blur" }
212
+ {
213
+ required: true,
214
+ message: t("system.common.validation.requiredInput", { field: t("system.config.field.name") }),
215
+ trigger: "blur"
216
+ },
217
+ {
218
+ max: 50,
219
+ message: t("system.common.validation.maxLength", { field: t("system.config.field.name"), max: 50 }),
220
+ trigger: "blur"
221
+ }
222
+ ],
223
+ type: [
224
+ {
225
+ required: true,
226
+ message: t("system.common.validation.requiredSelect", { field: t("system.config.field.type") }),
227
+ trigger: "change"
228
+ }
107
229
  ],
108
- type: [{ required: true, message: "请选择系统配置类型", trigger: "change" }],
109
230
  key: [
110
- { required: true, message: "请输入系统配置编码", trigger: "blur" },
111
- { max: 50, message: "配置key不能超过 50 个字符", trigger: "blur" }
231
+ {
232
+ required: true,
233
+ message: t("system.common.validation.requiredInput", { field: t("system.config.field.key") }),
234
+ trigger: "blur"
235
+ },
236
+ {
237
+ max: 50,
238
+ message: t("system.common.validation.maxLength", { field: t("system.config.field.key"), max: 50 }),
239
+ trigger: "blur"
240
+ }
112
241
  ],
113
- value: [{ required: true, message: "配置值不能为空", trigger: "blur" }],
114
- status: [{ required: true, message: "请选择状态", trigger: "change" }]
115
- });
242
+ value: [
243
+ {
244
+ required: true,
245
+ message: t("system.common.validation.requiredInput", { field: t("system.config.field.value") }),
246
+ trigger: "blur"
247
+ }
248
+ ],
249
+ status: [
250
+ {
251
+ required: true,
252
+ message: t("system.common.validation.requiredSelect", { field: t("system.common.field.status") }),
253
+ trigger: "change"
254
+ }
255
+ ]
256
+ }));
116
257
 
117
- const statusOptions: ProFormOption[] = [
118
- { label: "启用", value: Status.ENABLE },
119
- { label: "禁用", value: Status.DISABLE }
120
- ];
258
+ const statusOptions = computed<ProFormOption[]>(() => [
259
+ { label: t("common.status.enabled"), value: Status.ENABLE },
260
+ { label: t("common.status.disabled"), value: Status.DISABLE }
261
+ ]);
121
262
 
122
263
  /** 字典类系统配置与字典编码的映射关系。 */
123
264
  const BASE_CONFIG_DICT_CODE_MAP: Record<string, string> = {
@@ -131,45 +272,51 @@ const dictValueCode = computed(() => BASE_CONFIG_DICT_CODE_MAP[formData.key] ??
131
272
  const formFields = computed<ProFormField[]>(() => [
132
273
  {
133
274
  prop: "name",
134
- label: "配置名称",
275
+ label: t("system.config.field.name"),
135
276
  component: "input",
136
- props: { placeholder: "请输入配置名称", disabled: formData.id > 0 }
277
+ props: {
278
+ placeholder: t("system.common.validation.requiredInput", { field: t("system.config.field.name") }),
279
+ disabled: formData.id > 0
280
+ }
137
281
  },
138
282
  {
139
283
  prop: "site",
140
- label: "配置位置",
284
+ label: t("system.config.field.site"),
141
285
  component: "dict",
142
286
  props: { code: "base_config_site", disabled: formData.id > 0 }
143
287
  },
144
288
  {
145
289
  prop: "key",
146
- label: "配置键",
290
+ label: t("system.config.field.key"),
147
291
  component: "input",
148
- props: { placeholder: "请输入配置键", disabled: formData.id > 0 }
292
+ props: {
293
+ placeholder: t("system.common.validation.requiredInput", { field: t("system.config.field.key") }),
294
+ disabled: formData.id > 0
295
+ }
149
296
  },
150
297
  {
151
298
  prop: "type",
152
- label: "配置类型",
299
+ label: t("system.config.field.type"),
153
300
  component: "dict",
154
301
  props: { code: "base_config_type", disabled: formData.id > 0 }
155
302
  },
156
303
  {
157
304
  prop: "value",
158
- label: "配置值",
305
+ label: t("system.config.field.value"),
159
306
  component: "slot",
160
307
  slotName: "textValue",
161
308
  visible: model => model.type == BaseConfigType.TEXT
162
309
  },
163
310
  {
164
311
  prop: "value",
165
- label: "配置值",
312
+ label: t("system.config.field.value"),
166
313
  component: "slot",
167
314
  slotName: "imageValue",
168
315
  visible: model => model.type == BaseConfigType.IMAGE
169
316
  },
170
317
  {
171
318
  prop: "value",
172
- label: "配置值",
319
+ label: t("system.config.field.value"),
173
320
  component: "slot",
174
321
  slotName: "richTextValue",
175
322
  visible: model => model.type == BaseConfigType.RICH_TEXT,
@@ -177,60 +324,82 @@ const formFields = computed<ProFormField[]>(() => [
177
324
  },
178
325
  {
179
326
  prop: "value",
180
- label: "配置值",
327
+ label: t("system.config.field.value"),
181
328
  component: "slot",
182
329
  slotName: "dictValue",
183
330
  visible: model => model.type == BaseConfigType.DICT
184
331
  },
185
332
  {
186
333
  prop: "value",
187
- label: "配置值",
334
+ label: t("system.config.field.value"),
188
335
  component: "slot",
189
336
  slotName: "booleanValue",
190
337
  visible: model => model.type == BaseConfigType.BOOLEAN
191
338
  },
192
- { prop: "status", label: "状态", component: "radio-group", options: statusOptions }
339
+ {
340
+ prop: "translations",
341
+ label: t("system.translation.field.nameTranslations"),
342
+ component: "slot",
343
+ slotName: "nameTranslations",
344
+ colSpan: 24
345
+ },
346
+ {
347
+ prop: "translations",
348
+ label: t("system.translation.field.valueTranslations"),
349
+ component: "slot",
350
+ slotName: "valueTranslations",
351
+ visible: model => model.type == BaseConfigType.TEXT || model.type == BaseConfigType.RICH_TEXT,
352
+ colSpan: 24
353
+ },
354
+ { prop: "status", label: t("system.common.field.status"), component: "radio-group", options: statusOptions.value }
193
355
  ]);
194
356
 
195
357
  /** 系统配置表格列配置。 */
196
- const columns: ColumnProps[] = [
358
+ const columns = computed<ColumnProps[]>(() => [
197
359
  { type: "selection", width: 55 },
198
- { prop: "site", label: "配置位置", minWidth: 120, dictCode: "base_config_site", search: { el: "select" } },
199
- { prop: "name", label: "配置名称", minWidth: 140, search: { el: "input" } },
200
- { prop: "type", label: "配置类型", minWidth: 120, dictCode: "base_config_type", search: { el: "select" } },
360
+ { prop: "site", label: t("system.config.field.site"), minWidth: 120, dictCode: "base_config_site", search: { el: "select" } },
361
+ {
362
+ prop: "name",
363
+ label: t("system.config.field.name"),
364
+ minWidth: 140,
365
+ search: { el: "input" },
366
+ showOverflowTooltip: false,
367
+ render: scope => renderConfigNameCell(scope.row as BaseConfig)
368
+ },
369
+ { prop: "type", label: t("system.config.field.type"), minWidth: 120, dictCode: "base_config_type", search: { el: "select" } },
201
370
  {
202
371
  prop: "key",
203
- label: "配置键",
372
+ label: t("system.config.field.key"),
204
373
  minWidth: 160,
205
374
  search: { el: "input" },
206
375
  render: scope => renderConfigKeyCell(scope.row as BaseConfig)
207
376
  },
208
377
  {
209
378
  prop: "status",
210
- label: "状态",
379
+ label: t("system.common.field.status"),
211
380
  minWidth: 100,
212
381
  search: { el: "select" },
213
382
  cellType: "status",
214
383
  statusProps: {
215
384
  activeValue: Status.ENABLE,
216
385
  inactiveValue: Status.DISABLE,
217
- activeText: "启用",
218
- inactiveText: "禁用",
386
+ activeText: t("common.status.enabled"),
387
+ inactiveText: t("common.status.disabled"),
219
388
  disabled: () => !BUTTONS.value["base:config:status"],
220
389
  beforeChange: scope => handleBeforeSetStatus(scope.row as BaseConfig)
221
390
  }
222
391
  },
223
- { prop: "created_at", label: "创建时间", minWidth: 180 },
224
- { prop: "updated_at", label: "更新时间", minWidth: 180 },
392
+ { prop: "created_at", label: t("system.common.field.createdAt"), minWidth: 180 },
393
+ { prop: "updated_at", label: t("system.common.field.updatedAt"), minWidth: 180 },
225
394
  {
226
395
  prop: "operation",
227
- label: "操作",
396
+ label: t("system.common.field.operation"),
228
397
  width: 150,
229
398
  fixed: "right",
230
399
  cellType: "actions",
231
400
  actions: [
232
401
  {
233
- label: "编辑",
402
+ label: t("common.action.edit"),
234
403
  type: "primary",
235
404
  link: true,
236
405
  icon: EditPen,
@@ -239,7 +408,7 @@ const columns: ColumnProps[] = [
239
408
  onClick: (scope, params) => handleOpenDialog((params?.configId as number | undefined) ?? (scope.row as BaseConfig).id)
240
409
  },
241
410
  {
242
- label: "删除",
411
+ label: t("common.action.delete"),
243
412
  type: "danger",
244
413
  link: true,
245
414
  icon: Delete,
@@ -248,7 +417,18 @@ const columns: ColumnProps[] = [
248
417
  }
249
418
  ]
250
419
  }
251
- ];
420
+ ]);
421
+
422
+ /** 渲染系统配置名称翻译预览,并复用当前页面的编辑弹窗。 */
423
+ function renderConfigNameCell(row: BaseConfig) {
424
+ return h(DynamicTranslationCell, {
425
+ source: row.name,
426
+ translations: (row.translations ?? []).filter(
427
+ item => item.field === BaseConfigTranslationField.BASE_CONFIG_TRANSLATION_FIELD_NAME
428
+ ),
429
+ textField: "text"
430
+ });
431
+ }
252
432
 
253
433
  /**
254
434
  * 将配置键渲染为可悬停查看配置值的单元格。
@@ -283,7 +463,7 @@ function renderConfigValuePreview(row: BaseConfig) {
283
463
  fit: "contain",
284
464
  style: { width: "180px", height: "120px", borderRadius: "4px" }
285
465
  })
286
- : h("span", { class: "config-value-preview" }, "未配置图片");
466
+ : h("span", { class: "config-value-preview" }, t("system.config.message.imageMissing"));
287
467
  }
288
468
 
289
469
  if (row.type === BaseConfigType.BOOLEAN) {
@@ -302,24 +482,24 @@ function renderConfigValuePreview(row: BaseConfig) {
302
482
  if (row.type === BaseConfigType.RICH_TEXT) {
303
483
  return row.value
304
484
  ? h("div", { class: "config-rich-text-preview", innerHTML: row.value })
305
- : h("span", { class: "config-value-preview" }, "未配置富文本");
485
+ : h("span", { class: "config-value-preview" }, t("system.config.message.richTextMissing"));
306
486
  }
307
487
 
308
488
  const value = row.value;
309
- return h("span", { class: "config-value-preview" }, value || "未配置");
489
+ return h("span", { class: "config-value-preview" }, value || t("system.config.message.valueMissing"));
310
490
  }
311
491
 
312
492
  /** 系统配置顶部按钮配置。 */
313
- const headerActions: HeaderActionProps[] = [
493
+ const headerActions = computed<HeaderActionProps[]>(() => [
314
494
  {
315
- label: "新增",
495
+ label: t("common.action.create"),
316
496
  type: "success",
317
497
  icon: CirclePlus,
318
498
  hidden: () => !BUTTONS.value["base:config:create"],
319
499
  onClick: () => handleOpenDialog()
320
500
  },
321
501
  {
322
- label: "删除",
502
+ label: t("common.action.delete"),
323
503
  type: "danger",
324
504
  icon: Delete,
325
505
  hidden: () => !BUTTONS.value["base:config:delete"],
@@ -327,18 +507,19 @@ const headerActions: HeaderActionProps[] = [
327
507
  onClick: scope => handleDelete(scope.selectedList as BaseConfig[])
328
508
  },
329
509
  {
330
- label: "刷新缓存",
510
+ label: t("system.common.action.refreshCache"),
331
511
  type: "primary",
332
512
  icon: RefreshLeft,
333
513
  hidden: () => !BUTTONS.value["base:config:refresh"],
334
514
  onClick: () => handleRefreshCache()
335
515
  }
336
- ];
516
+ ]);
337
517
 
338
518
  /**
339
519
  * 请求系统配置列表,并由 ProTable 统一维护分页与搜索参数。
340
520
  */
341
521
  async function requestBaseConfigTable(params: PageBaseConfigRequest) {
522
+ await loadEnabledBaseLanguages();
342
523
  const data = await defBaseConfigService.PageBaseConfig(buildPageRequest(params));
343
524
  return { data: { list: data.base_configs ?? [], total: data.total } };
344
525
  }
@@ -353,15 +534,14 @@ function refreshTable() {
353
534
  /**
354
535
  * 打开系统配置弹窗。
355
536
  */
356
- function handleOpenDialog(configId?: number) {
537
+ async function handleOpenDialog(configId?: number) {
538
+ await loadEnabledBaseLanguages();
357
539
  resetForm();
358
- dialog.title = configId ? "修改系统配置" : "新增系统配置";
540
+ dialog.titleKey = configId ? "system.common.action.editResource" : "system.common.action.createResource";
359
541
  dialog.visible = true;
360
542
  if (!configId) return;
361
543
 
362
- defBaseConfigService.GetBaseConfig({ id: configId }).then(data => {
363
- Object.assign(formData, data);
364
- });
544
+ Object.assign(formData, await defBaseConfigService.GetBaseConfig({ id: configId }));
365
545
  }
366
546
 
367
547
  /**
@@ -384,6 +564,7 @@ function resetForm() {
384
564
  formData.type = BaseConfigType.UNKNOWN_BCT;
385
565
  formData.key = "";
386
566
  formData.value = "";
567
+ formData.translations = [];
387
568
  formData.status = Status.ENABLE;
388
569
  }
389
570
 
@@ -402,7 +583,11 @@ function handleSubmit() {
402
583
  ? defBaseConfigService.UpdateBaseConfig({ base_config: submitData })
403
584
  : defBaseConfigService.CreateBaseConfig({ base_config: submitData });
404
585
  request.then(() => {
405
- ElMessage.success(submitData.id ? "修改系统配置成功" : "新增系统配置成功");
586
+ ElMessage.success(
587
+ t(submitData.id ? "system.common.message.updateSuccess" : "system.common.message.createSuccess", {
588
+ resource: t("system.config.resource")
589
+ })
590
+ );
406
591
  handleCloseDialog();
407
592
  refreshTable();
408
593
  });
@@ -414,7 +599,7 @@ function handleSubmit() {
414
599
  */
415
600
  const handleRefreshCache = useDebounceFn(() => {
416
601
  defBaseConfigService.RefreshBaseConfigCache({}).then(() => {
417
- ElMessage.success("刷新成功");
602
+ ElMessage.success(t("system.common.message.refreshSuccess"));
418
603
  });
419
604
  }, 1000);
420
605
 
@@ -423,16 +608,25 @@ const handleRefreshCache = useDebounceFn(() => {
423
608
  */
424
609
  async function handleBeforeSetStatus(row: BaseConfig) {
425
610
  const nextStatus = row.status === Status.ENABLE ? Status.DISABLE : Status.ENABLE;
426
- const text = nextStatus === Status.ENABLE ? "启用" : "禁用";
611
+ const text = t(nextStatus === Status.ENABLE ? "common.status.enabled" : "common.status.disabled");
427
612
  const configName = row.name || row.key || `ID:${row.id}`;
428
613
  try {
429
- await ElMessageBox.confirm(`是否确定${text}配置?\n配置名称:${configName}`, "提示", {
430
- confirmButtonText: "确认",
431
- cancelButtonText: "取消",
432
- type: "warning"
433
- });
614
+ await ElMessageBox.confirm(
615
+ t("system.common.dialog.statusChange", {
616
+ action: text,
617
+ resource: t("system.config.resource"),
618
+ field: t("system.config.field.name"),
619
+ value: configName
620
+ }),
621
+ t("common.title.notice"),
622
+ {
623
+ confirmButtonText: t("common.action.confirm"),
624
+ cancelButtonText: t("common.action.cancel"),
625
+ type: "warning"
626
+ }
627
+ );
434
628
  await defBaseConfigService.SetBaseConfigStatus({ id: row.id, status: nextStatus });
435
- ElMessage.success(`${text}成功`);
629
+ ElMessage.success(t("system.common.message.statusSuccess", { action: text }));
436
630
  refreshTable();
437
631
  return true;
438
632
  } catch {
@@ -455,29 +649,29 @@ function handleDelete(selected?: number | string | Array<number | string> | Base
455
649
  : normalizeSelectedIds(selected as number | string | Array<number | string>)
456
650
  ).join(",");
457
651
  if (!configIds) {
458
- ElMessage.warning("请勾选删除项");
652
+ ElMessage.warning(t("system.common.message.selectDeleteItem"));
459
653
  return;
460
654
  }
461
655
 
462
656
  const confirmMessage = configList.length
463
657
  ? configList.length === 1
464
- ? `是否确定删除配置?\n配置名称:${configList[0].name || configList[0].key || `ID:${configList[0].id}`}`
465
- : `确认删除已选中的 ${configList.length} 项系统配置吗?`
466
- : "确认删除已选中的系统配置吗?";
658
+ ? `${t("system.common.dialog.deleteSingle", { resource: t("system.config.resource") })}\n${t("system.common.dialog.resourceField", { field: t("system.config.field.name"), value: configList[0].name || configList[0].key || `ID:${configList[0].id}` })}`
659
+ : t("system.common.dialog.deleteBatch", { count: configList.length, unit: "", resource: t("system.config.resource") })
660
+ : t("system.common.dialog.deleteSelected", { resource: t("system.config.resource") });
467
661
 
468
- ElMessageBox.confirm(confirmMessage, "警告", {
469
- confirmButtonText: "确定",
470
- cancelButtonText: "取消",
662
+ ElMessageBox.confirm(confirmMessage, t("common.title.warning"), {
663
+ confirmButtonText: t("common.action.confirm"),
664
+ cancelButtonText: t("common.action.cancel"),
471
665
  type: "warning"
472
666
  }).then(
473
667
  () => {
474
668
  defBaseConfigService.DeleteBaseConfig({ id: configIds }).then(() => {
475
- ElMessage.success("删除系统配置成功");
669
+ ElMessage.success(t("system.common.message.deleteSuccess", { resource: t("system.config.resource") }));
476
670
  refreshTable();
477
671
  });
478
672
  },
479
673
  () => {
480
- ElMessage.info("已取消删除系统配置");
674
+ ElMessage.info(t("system.common.dialog.cancelDelete", { resource: t("system.config.resource") }));
481
675
  }
482
676
  );
483
677
  }