@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
@@ -4,7 +4,7 @@
4
4
  <TreeFilter
5
5
  :key="`dept-filter-${selectedTenantId ?? 0}`"
6
6
  label="name"
7
- title="部门列表"
7
+ :title="t('system.user.title.departmentList')"
8
8
  :request-api="requestDeptTreeFilter"
9
9
  :show-all="false"
10
10
  :default-value="deptFilterValue"
@@ -26,7 +26,7 @@
26
26
  <FormDialog
27
27
  v-model="dialog.visible"
28
28
  ref="formDialogRef"
29
- :title="dialog.title"
29
+ :title="t(dialog.editing ? 'system.user.action.edit' : 'system.user.action.create')"
30
30
  width="800px"
31
31
  :model="formData"
32
32
  :fields="formFields"
@@ -43,7 +43,7 @@
43
43
  <FormDialog
44
44
  v-model="resetPwdDialog.visible"
45
45
  ref="resetPwdFormDialogRef"
46
- :title="resetPwdDialog.title"
46
+ :title="t('system.user.title.resetPassword', { name: resetPwdTargetName })"
47
47
  width="520px"
48
48
  :model="resetPwdForm"
49
49
  :fields="resetPwdFields"
@@ -72,7 +72,12 @@ import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/co
72
72
  import TreeFilter from "@liujitcn/kratos-admin-core/components/TreeFilter/index.vue";
73
73
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
74
74
  import { defBaseUserService } from "@liujitcn/kratos-admin-system/api/system/base_user";
75
- import type { BaseUser, BaseUserForm, PageBaseUserRequest, ResetBaseUserPasswordRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_user";
75
+ import type {
76
+ BaseUser,
77
+ BaseUserForm,
78
+ PageBaseUserRequest,
79
+ ResetBaseUserPasswordRequest
80
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_user";
76
81
  import { defBaseDeptService } from "@liujitcn/kratos-admin-system/api/system/base_dept";
77
82
  import { defBaseRoleService } from "@liujitcn/kratos-admin-system/api/system/base_role";
78
83
  import { defBasePostService } from "@liujitcn/kratos-admin-system/api/system/base_post";
@@ -80,14 +85,10 @@ import { defBaseTenantService } from "@liujitcn/kratos-admin-system/api/system/b
80
85
  import type { SelectOptionResponse_Option, TreeOptionResponse_Option } from "@liujitcn/kratos-admin-system/rpc/common/v1/common";
81
86
  import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
82
87
  import { buildPageRequest, normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
83
- import {
84
- PASSWORD_CRYPTO_SCENE,
85
- PASSWORD_STRENGTH_ERROR_MESSAGE,
86
- encryptPassword,
87
- validatePasswordStrengthValue
88
- } from "@liujitcn/kratos-admin-core/security";
88
+ import { PASSWORD_CRYPTO_SCENE, encryptPassword, validatePasswordStrengthValue } from "@liujitcn/kratos-admin-core/security";
89
89
  import { DEFAULT_TENANT_CODE, requestTenantOptions } from "@liujitcn/kratos-admin-core/tenant";
90
90
  import { useUserStore } from "@liujitcn/kratos-admin-core/stores/runtime";
91
+ import { t } from "@liujitcn/kratos-admin-core";
91
92
 
92
93
  /** 用户表单状态,前端保留明文密码并在提交前加密。 */
93
94
  interface BaseUserFormState extends Omit<BaseUserForm, "dept_id" | "post_id" | "pwd" | "role_id" | "tenant_id"> {
@@ -135,11 +136,10 @@ const deptFilterValue = ref("");
135
136
 
136
137
  const dialog = reactive({
137
138
  visible: false,
138
- title: "新增用户"
139
+ editing: false
139
140
  });
140
141
  const resetPwdDialog = reactive({
141
- visible: false,
142
- title: "重置密码"
142
+ visible: false
143
143
  });
144
144
 
145
145
  const formData = reactive<BaseUserFormState>({
@@ -178,66 +178,120 @@ const resetPwdForm = reactive<ResetBaseUserPasswordFormState>({
178
178
  });
179
179
  const resetPwdTargetName = ref("");
180
180
 
181
- const rules = reactive({
182
- tenant_id: [{ required: true, message: "所属租户不能为空", trigger: "change" }],
181
+ const rules = computed(() => ({
182
+ tenant_id: [
183
+ {
184
+ required: true,
185
+ message: t("system.common.validation.requiredSelect", { field: t("system.user.field.tenant") }),
186
+ trigger: "change"
187
+ }
188
+ ],
183
189
  user_name: [
184
- { required: true, message: "用户账号不能为空", trigger: "blur" },
185
- { max: 50, message: "用户账号不能超过 50 个字符", trigger: "blur" }
190
+ {
191
+ required: true,
192
+ message: t("system.common.validation.requiredInput", { field: t("system.user.field.userName") }),
193
+ trigger: "blur"
194
+ },
195
+ {
196
+ max: 50,
197
+ message: t("system.common.validation.maxLength", { field: t("system.user.field.userName"), max: 50 }),
198
+ trigger: "blur"
199
+ }
186
200
  ],
187
201
  user_code: [
188
- { required: true, message: "用户编号不能为空", trigger: "blur" },
189
- { max: 30, message: "用户编号不能超过 30 个字符", trigger: "blur" }
202
+ {
203
+ required: true,
204
+ message: t("system.common.validation.requiredInput", { field: t("system.user.field.userCode") }),
205
+ trigger: "blur"
206
+ },
207
+ {
208
+ max: 30,
209
+ message: t("system.common.validation.maxLength", { field: t("system.user.field.userCode"), max: 30 }),
210
+ trigger: "blur"
211
+ }
190
212
  ],
191
213
  nick_name: [
192
- { required: true, message: "用户昵称不能为空", trigger: "blur" },
193
- { max: 30, message: "用户昵称不能超过 30 个字符", trigger: "blur" }
214
+ {
215
+ required: true,
216
+ message: t("system.common.validation.requiredInput", { field: t("system.user.field.nickName") }),
217
+ trigger: "blur"
218
+ },
219
+ {
220
+ max: 30,
221
+ message: t("system.common.validation.maxLength", { field: t("system.user.field.nickName"), max: 30 }),
222
+ trigger: "blur"
223
+ }
224
+ ],
225
+ dept_id: [
226
+ {
227
+ required: true,
228
+ message: t("system.common.validation.requiredSelect", { field: t("system.user.field.department") }),
229
+ trigger: "change"
230
+ }
231
+ ],
232
+ role_id: [
233
+ {
234
+ required: true,
235
+ message: t("system.common.validation.requiredSelect", { field: t("system.user.field.role") }),
236
+ trigger: "change"
237
+ }
194
238
  ],
195
- dept_id: [{ required: true, message: "用户部门不能为空", trigger: "change" }],
196
- role_id: [{ required: true, message: "用户角色不能为空", trigger: "change" }],
197
239
  phone: [
198
- { max: 20, message: "手机号不能超过 20 个字符", trigger: "blur" },
240
+ { max: 20, message: t("system.common.validation.maxLength", { field: t("common.field.phone"), max: 20 }), trigger: "blur" },
199
241
  {
200
242
  pattern: /^1[3-9]\d{9}$/,
201
- message: "请输入正确的手机号码",
243
+ message: t("common.validation.phoneInvalid"),
202
244
  trigger: "blur"
203
245
  }
204
246
  ],
205
247
  pwd: [
206
- { required: true, message: "请输入密码", trigger: "blur" },
248
+ { required: true, message: t("core.password.required"), trigger: "blur" },
207
249
  { validator: validatePasswordField, trigger: "blur" }
208
250
  ],
209
- status: [{ required: true, message: "用户状态不能为空", trigger: "change" }],
210
- remark: [{ max: 500, message: "备注不能超过 500 个字符", trigger: "blur" }]
211
- });
212
- const resetPwdRules = reactive({
251
+ status: [
252
+ {
253
+ required: true,
254
+ message: t("system.common.validation.requiredSelect", { field: t("system.common.field.status") }),
255
+ trigger: "change"
256
+ }
257
+ ],
258
+ remark: [
259
+ {
260
+ max: 500,
261
+ message: t("system.common.validation.maxLength", { field: t("system.common.field.remark"), max: 500 }),
262
+ trigger: "blur"
263
+ }
264
+ ]
265
+ }));
266
+ const resetPwdRules = computed(() => ({
213
267
  pwd: [
214
- { required: true, message: "请输入新密码", trigger: "blur" },
268
+ { required: true, message: t("system.user.placeholder.newPassword"), trigger: "blur" },
215
269
  { validator: validatePasswordField, trigger: "blur" }
216
270
  ]
217
- });
271
+ }));
218
272
 
219
273
  const basedDeptOptions = ref<TreeOptionResponse_Option[]>([]);
220
274
  const baseRoleOptions = ref<SelectOptionResponse_Option[]>([]);
221
275
  const basePostOptions = ref<SelectOptionResponse_Option[]>([]);
222
276
  const tenantOptions = ref<SelectOptionResponse_Option[]>([]);
223
- const statusOptions: ProFormOption[] = [
224
- { label: "启用", value: Status.ENABLE },
225
- { label: "禁用", value: Status.DISABLE }
226
- ];
227
- const resetPwdFields: ProFormField[] = [
277
+ const statusOptions = computed<ProFormOption[]>(() => [
278
+ { label: t("common.status.enabled"), value: Status.ENABLE },
279
+ { label: t("common.status.disabled"), value: Status.DISABLE }
280
+ ]);
281
+ const resetPwdFields = computed<ProFormField[]>(() => [
228
282
  {
229
283
  prop: "pwd",
230
- label: "新密码",
284
+ label: t("system.user.field.newPassword"),
231
285
  component: "password",
232
- props: { placeholder: "请输入新密码", showPassword: true }
286
+ props: { placeholder: t("system.user.placeholder.newPassword"), showPassword: true }
233
287
  },
234
288
  {
235
289
  prop: "resetPwdStrength",
236
- label: "强度提示",
290
+ label: t("system.user.field.passwordStrength"),
237
291
  component: "slot",
238
292
  slotName: "resetPwdStrength"
239
293
  }
240
- ];
294
+ ]);
241
295
 
242
296
  /** 当前登录账号是否默认租户。 */
243
297
  const isDefaultTenant = computed(() => userStore.userInfo.tenant_code === DEFAULT_TENANT_CODE);
@@ -255,10 +309,10 @@ const isSuperEditUser = computed(() => Boolean(formData.id && formData.user_name
255
309
  const formFields = computed<ProFormField[]>(() => [
256
310
  {
257
311
  prop: "tenant_id",
258
- label: "所属租户",
312
+ label: t("system.user.field.tenant"),
259
313
  component: "select",
260
314
  props: {
261
- placeholder: "请选择所属租户",
315
+ placeholder: t("system.user.placeholder.tenant"),
262
316
  filterable: true,
263
317
  disabled: Boolean(formData.id),
264
318
  onChange: handleFormTenantChange
@@ -268,31 +322,36 @@ const formFields = computed<ProFormField[]>(() => [
268
322
  },
269
323
  {
270
324
  prop: "user_name",
271
- label: "用户账号",
325
+ label: t("system.user.field.userName"),
272
326
  component: "input",
273
- props: { placeholder: "请输入用户账号", disabled: Boolean(formData.id) }
327
+ props: { placeholder: t("system.user.placeholder.userName"), disabled: Boolean(formData.id) }
274
328
  },
275
329
  {
276
330
  prop: "user_code",
277
- label: "用户编号",
331
+ label: t("system.user.field.userCode"),
278
332
  component: "input",
279
- props: { placeholder: "请输入用户编号", disabled: Boolean(formData.id) }
333
+ props: { placeholder: t("system.user.placeholder.userCode"), disabled: Boolean(formData.id) }
334
+ },
335
+ {
336
+ prop: "nick_name",
337
+ label: t("system.user.field.nickName"),
338
+ component: "input",
339
+ props: { placeholder: t("system.user.placeholder.nickName") }
280
340
  },
281
- { prop: "nick_name", label: "用户昵称", component: "input", props: { placeholder: "请输入用户昵称" } },
282
341
  {
283
342
  prop: "role_id",
284
- label: "角色",
343
+ label: t("system.user.field.role"),
285
344
  component: "select",
286
345
  options: baseRoleOptions.value.map(item => ({ label: item.label, value: item.value, disabled: item.disabled })),
287
- props: { placeholder: "请选择", disabled: isProtectedUserRole.value }
346
+ props: { placeholder: t("common.placeholder.select"), disabled: isProtectedUserRole.value }
288
347
  },
289
348
  {
290
349
  prop: "dept_id",
291
- label: "用户部门",
350
+ label: t("system.user.field.department"),
292
351
  component: "tree-select",
293
352
  options: basedDeptOptions.value as unknown as ProFormOption[],
294
353
  props: {
295
- placeholder: "请选择用户部门",
354
+ placeholder: t("system.user.placeholder.department"),
296
355
  filterable: true,
297
356
  checkStrictly: true,
298
357
  renderAfterExpand: false,
@@ -301,35 +360,45 @@ const formFields = computed<ProFormField[]>(() => [
301
360
  },
302
361
  {
303
362
  prop: "post_id",
304
- label: "用户岗位",
363
+ label: t("system.user.field.post"),
305
364
  component: "select",
306
365
  options: basePostOptions.value.map(item => ({ label: item.label, value: item.value, disabled: item.disabled })),
307
- props: { placeholder: "请选择用户岗位", clearable: true, filterable: true }
366
+ props: { placeholder: t("system.user.placeholder.post"), clearable: true, filterable: true }
367
+ },
368
+ {
369
+ prop: "phone",
370
+ label: t("common.field.phone"),
371
+ component: "input",
372
+ props: { placeholder: t("common.validation.phoneRequired") }
308
373
  },
309
- { prop: "phone", label: "手机号码", component: "input", props: { placeholder: "请输入手机号码" } },
310
374
  {
311
375
  prop: "pwd",
312
- label: "密码",
376
+ label: t("system.user.field.password"),
313
377
  component: "password",
314
- props: { placeholder: "请输入密码", showPassword: true },
378
+ props: { placeholder: t("system.user.placeholder.password"), showPassword: true },
315
379
  visible: model => !model.id
316
380
  },
317
381
  {
318
382
  prop: "passwordStrength",
319
- label: "强度提示",
383
+ label: t("system.user.field.passwordStrength"),
320
384
  component: "slot",
321
385
  slotName: "passwordStrength",
322
386
  visible: model => !model.id
323
387
  },
324
- { prop: "gender", label: "性别", component: "dict", props: { code: "base_user_gender" } },
388
+ { prop: "gender", label: t("system.user.field.gender"), component: "dict", props: { code: "base_user_gender" } },
325
389
  {
326
390
  prop: "status",
327
- label: "状态",
391
+ label: t("system.common.field.status"),
328
392
  component: "radio-group",
329
- options: statusOptions,
393
+ options: statusOptions.value,
330
394
  props: { disabled: isSuperEditUser.value }
331
395
  },
332
- { prop: "remark", label: "备注", component: "textarea", props: { placeholder: "请输入备注" } }
396
+ {
397
+ prop: "remark",
398
+ label: t("system.common.field.remark"),
399
+ component: "textarea",
400
+ props: { placeholder: t("system.common.placeholder.remark") }
401
+ }
333
402
  ]);
334
403
 
335
404
  /** 用户表格列配置。 */
@@ -339,7 +408,7 @@ const columns = computed<ColumnProps[]>(() => [
339
408
  ? ([
340
409
  {
341
410
  prop: "tenant_id",
342
- label: "租户",
411
+ label: t("system.user.field.tenantShort"),
343
412
  minWidth: 140,
344
413
  showOverflowTooltip: true,
345
414
  search: { el: "select", key: "tenant_id", props: { filterable: true }, order: 1 },
@@ -347,41 +416,54 @@ const columns = computed<ColumnProps[]>(() => [
347
416
  }
348
417
  ] satisfies ColumnProps[])
349
418
  : []),
350
- { prop: "user_name", label: "用户账号", minWidth: 140, search: { el: "input" } },
351
- { prop: "user_code", label: "用户编号", minWidth: 140, search: { el: "input" } },
352
- { prop: "nick_name", label: "昵称", minWidth: 100, search: { el: "input" } },
353
- { prop: "role_id", label: "角色", minWidth: 140, enum: requestRoleOptions },
354
- { prop: "dept_id", label: "部门", minWidth: 180, showOverflowTooltip: true, enum: requestDeptOptions },
355
- { prop: "post_id", label: "岗位", minWidth: 120, enum: requestPostOptions },
356
- { prop: "phone", label: "手机号码", minWidth: 130, search: { el: "input" } },
357
- { prop: "gender", label: "性别", minWidth: 90, align: "center", dictCode: "base_user_gender", search: { el: "select" } },
419
+ { prop: "user_name", label: t("system.user.field.userName"), minWidth: 140, search: { el: "input" } },
420
+ { prop: "user_code", label: t("system.user.field.userCode"), minWidth: 140, search: { el: "input" } },
421
+ { prop: "nick_name", label: t("system.user.field.nickNameShort"), minWidth: 100, search: { el: "input" } },
422
+ { prop: "role_id", label: t("system.user.field.role"), minWidth: 140, enum: requestRoleOptions },
423
+ {
424
+ prop: "dept_id",
425
+ label: t("system.user.field.departmentShort"),
426
+ minWidth: 180,
427
+ showOverflowTooltip: true,
428
+ enum: requestDeptOptions
429
+ },
430
+ { prop: "post_id", label: t("system.user.field.postShort"), minWidth: 120, enum: requestPostOptions },
431
+ { prop: "phone", label: t("common.field.phone"), minWidth: 130, search: { el: "input" } },
432
+ {
433
+ prop: "gender",
434
+ label: t("system.user.field.gender"),
435
+ minWidth: 90,
436
+ align: "center",
437
+ dictCode: "base_user_gender",
438
+ search: { el: "select" }
439
+ },
358
440
  {
359
441
  prop: "status",
360
- label: "状态",
442
+ label: t("system.common.field.status"),
361
443
  minWidth: 100,
362
444
  search: { el: "select" },
363
445
  cellType: "status",
364
446
  statusProps: {
365
447
  activeValue: Status.ENABLE,
366
448
  inactiveValue: Status.DISABLE,
367
- activeText: "启用",
368
- inactiveText: "禁用",
449
+ activeText: t("common.status.enabled"),
450
+ inactiveText: t("common.status.disabled"),
369
451
  disabled: scope => isProtectedManagementUser(scope.row as BaseUser) || !BUTTONS.value["base:user:status"],
370
452
  beforeChange: scope => handleBeforeSetStatus(scope.row as BaseUser)
371
453
  }
372
454
  },
373
- { prop: "remark", label: "备注", minWidth: 160 },
374
- { prop: "created_at", label: "创建时间", minWidth: 180 },
375
- { prop: "updated_at", label: "更新时间", minWidth: 180 },
455
+ { prop: "remark", label: t("system.common.field.remark"), minWidth: 160 },
456
+ { prop: "created_at", label: t("system.common.field.createdAt"), minWidth: 180 },
457
+ { prop: "updated_at", label: t("system.common.field.updatedAt"), minWidth: 180 },
376
458
  {
377
459
  prop: "operation",
378
- label: "操作",
460
+ label: t("system.common.field.action"),
379
461
  width: 260,
380
462
  fixed: "right",
381
463
  cellType: "actions",
382
464
  actions: [
383
465
  {
384
- label: "重置密码",
466
+ label: t("system.user.action.resetPassword"),
385
467
  type: "primary",
386
468
  link: true,
387
469
  icon: RefreshLeft,
@@ -389,7 +471,7 @@ const columns = computed<ColumnProps[]>(() => [
389
471
  onClick: scope => handleResetPassword(scope.row as BaseUser)
390
472
  },
391
473
  {
392
- label: "编辑",
474
+ label: t("common.action.edit"),
393
475
  type: "primary",
394
476
  link: true,
395
477
  icon: EditPen,
@@ -398,7 +480,7 @@ const columns = computed<ColumnProps[]>(() => [
398
480
  onClick: (scope, params) => handleOpenDialog((params?.userId as number | undefined) ?? (scope.row as BaseUser).id)
399
481
  },
400
482
  {
401
- label: "删除",
483
+ label: t("common.action.delete"),
402
484
  type: "danger",
403
485
  link: true,
404
486
  icon: Delete,
@@ -410,23 +492,23 @@ const columns = computed<ColumnProps[]>(() => [
410
492
  ]);
411
493
 
412
494
  /** 用户顶部按钮配置。 */
413
- const headerActions: HeaderActionProps[] = [
495
+ const headerActions = computed<HeaderActionProps[]>(() => [
414
496
  {
415
- label: "新增",
497
+ label: t("common.action.create"),
416
498
  type: "success",
417
499
  icon: CirclePlus,
418
500
  hidden: () => !BUTTONS.value["base:user:create"],
419
501
  onClick: () => handleOpenDialog()
420
502
  },
421
503
  {
422
- label: "删除",
504
+ label: t("common.action.delete"),
423
505
  type: "danger",
424
506
  icon: Delete,
425
507
  hidden: () => !BUTTONS.value["base:user:delete"],
426
508
  disabled: scope => !scope.selectedList.length,
427
509
  onClick: scope => handleDelete(scope.selectedList as BaseUser[])
428
510
  }
429
- ];
511
+ ]);
430
512
 
431
513
  /**
432
514
  * 递归转换部门树筛选数据,适配 TreeFilter 组件的 id/name 字段。
@@ -442,10 +524,7 @@ function transformDeptFilterNodes(options: TreeOptionResponse_Option[] = []): De
442
524
  /**
443
525
  * 将部门树选项转换为完整路径标签,便于扁平列表关联字段按部门 ID 映射展示。
444
526
  */
445
- function transformDeptOptionPaths(
446
- options: TreeOptionResponse_Option[] = [],
447
- parentPath = ""
448
- ): TreeOptionResponse_Option[] {
527
+ function transformDeptOptionPaths(options: TreeOptionResponse_Option[] = [], parentPath = ""): TreeOptionResponse_Option[] {
449
528
  return options.map(option => {
450
529
  const label = option.label || "";
451
530
  const fullPath = [parentPath, label].filter(Boolean).join("/");
@@ -574,7 +653,7 @@ async function handleFormTenantChange() {
574
653
  async function handleOpenDialog(id?: number) {
575
654
  resetForm();
576
655
  await loadTenantOptions();
577
- dialog.title = id ? "修改用户" : "新增用户";
656
+ dialog.editing = Boolean(id);
578
657
  dialog.visible = true;
579
658
  if (!id) {
580
659
  await loadFormOptions();
@@ -629,7 +708,6 @@ function handleResetPassword(row: BaseUser) {
629
708
  resetPwdForm.id = row.id;
630
709
  resetPwdForm.pwd = "";
631
710
  resetPwdTargetName.value = row.nick_name || row.user_name || `ID:${row.id}`;
632
- resetPwdDialog.title = `重置密码:${resetPwdTargetName.value}`;
633
711
  resetPwdDialog.visible = true;
634
712
  }
635
713
 
@@ -654,7 +732,7 @@ async function handleConfirmResetPassword() {
654
732
 
655
733
  const pwd = await encryptPassword(resetPwdForm.pwd, PASSWORD_CRYPTO_SCENE.RESET_BASE_USER_PASSWORD);
656
734
  defBaseUserService.ResetBaseUserPassword({ id: resetPwdForm.id, pwd }).then(() => {
657
- ElMessage.success(`重置密码成功\n用户名称:${resetPwdTargetName.value}`);
735
+ ElMessage.success(t("system.user.message.resetPasswordSuccess", { name: resetPwdTargetName.value }));
658
736
  handleCloseResetPasswordDialog();
659
737
  });
660
738
  });
@@ -676,7 +754,7 @@ const handleSubmit = useDebounceFn(() => {
676
754
  ? defBaseUserService.UpdateBaseUser({ base_user: baseUser })
677
755
  : defBaseUserService.CreateBaseUser({ base_user: baseUser });
678
756
  request.then(() => {
679
- ElMessage.success(submitData.id ? "修改用户成功" : "新增用户成功");
757
+ ElMessage.success(t(submitData.id ? "system.user.message.updateSuccess" : "system.user.message.createSuccess"));
680
758
  handleCloseDialog();
681
759
  refreshTable();
682
760
  });
@@ -688,21 +766,21 @@ const handleSubmit = useDebounceFn(() => {
688
766
  */
689
767
  async function handleBeforeSetStatus(row: BaseUser) {
690
768
  if (isProtectedManagementUser(row)) {
691
- ElMessage.warning("内置管理员账号只能通过个人中心修改");
769
+ ElMessage.warning(t("system.user.message.protectedAccount"));
692
770
  return false;
693
771
  }
694
772
 
695
773
  const nextStatus = row.status === Status.ENABLE ? Status.DISABLE : Status.ENABLE;
696
- const text = nextStatus === Status.ENABLE ? "启用" : "禁用";
697
- const user_name = row.nick_name || row.user_name || `ID:${row.id}`;
774
+ const action = t(nextStatus === Status.ENABLE ? "common.status.enabled" : "common.status.disabled");
775
+ const userName = row.nick_name || row.user_name || `ID:${row.id}`;
698
776
  try {
699
- await ElMessageBox.confirm(`是否确定${text}用户?\n用户名称:${user_name}`, "提示", {
700
- confirmButtonText: "确认",
701
- cancelButtonText: "取消",
777
+ await ElMessageBox.confirm(t("system.user.message.confirmStatus", { action, name: userName }), t("common.title.notice"), {
778
+ confirmButtonText: t("common.action.confirm"),
779
+ cancelButtonText: t("common.action.cancel"),
702
780
  type: "warning"
703
781
  });
704
782
  await defBaseUserService.SetBaseUserStatus({ id: row.id, status: nextStatus });
705
- ElMessage.success(`${text}成功`);
783
+ ElMessage.success(t("system.common.message.statusSuccess", { action }));
706
784
  refreshTable();
707
785
  return true;
708
786
  } catch {
@@ -720,36 +798,38 @@ function handleDelete(selected?: number | string | Array<number | string> | Base
720
798
  ? [selected]
721
799
  : [];
722
800
  if (userList.some(isProtectedManagementUser)) {
723
- ElMessage.warning("内置管理员账号只能通过个人中心修改");
801
+ ElMessage.warning(t("system.user.message.protectedAccount"));
724
802
  return;
725
803
  }
726
804
  const userIds = normalizeSelectedIds(
727
805
  userList.length ? userList.map(item => item.id) : (selected as number | string | Array<number | string> | undefined)
728
806
  ).join(",");
729
807
  if (!userIds) {
730
- ElMessage.warning("请勾选删除项");
808
+ ElMessage.warning(t("system.common.message.selectDeleteItem"));
731
809
  return;
732
810
  }
733
811
 
734
812
  const confirmMessage = userList.length
735
813
  ? userList.length === 1
736
- ? `是否确定删除用户?\n用户名称:${userList[0].nick_name || userList[0].user_name || `ID:${userList[0].id}`}`
737
- : `确认删除已选中的 ${userList.length} 个用户吗?`
738
- : "确认删除已选中的用户吗?";
739
-
740
- ElMessageBox.confirm(confirmMessage, "警告", {
741
- confirmButtonText: "确定",
742
- cancelButtonText: "取消",
814
+ ? t("system.user.message.confirmDeleteSingle", {
815
+ name: userList[0].nick_name || userList[0].user_name || `ID:${userList[0].id}`
816
+ })
817
+ : t("system.user.message.confirmDeleteBatch", { count: userList.length })
818
+ : t("system.user.message.confirmDeleteSelected");
819
+
820
+ ElMessageBox.confirm(confirmMessage, t("common.title.warning"), {
821
+ confirmButtonText: t("common.action.confirm"),
822
+ cancelButtonText: t("common.action.cancel"),
743
823
  type: "warning"
744
824
  }).then(
745
825
  () => {
746
826
  defBaseUserService.DeleteBaseUser({ id: userIds }).then(() => {
747
- ElMessage.success("删除用户成功");
827
+ ElMessage.success(t("system.user.message.deleteSuccess"));
748
828
  refreshTable();
749
829
  });
750
830
  },
751
831
  () => {
752
- ElMessage.info("已取消删除用户");
832
+ ElMessage.info(t("system.user.message.deleteCanceled"));
753
833
  }
754
834
  );
755
835
  }
@@ -768,7 +848,7 @@ function validatePasswordField(_rule: unknown, value: string, callback: (error?:
768
848
  }
769
849
  const result = validatePasswordStrengthValue(value);
770
850
  if (!result.valid) {
771
- callback(new Error(result.message || PASSWORD_STRENGTH_ERROR_MESSAGE));
851
+ callback(new Error(t("core.password.error")));
772
852
  return;
773
853
  }
774
854
  callback();