@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
@@ -3,28 +3,34 @@
3
3
  <div class="table-box">
4
4
  <ProTable ref="proTable" row-key="id" :columns="columns" :request-api="requestBaseApiTable" />
5
5
 
6
- <el-drawer v-model="detailDrawer.visible" title="API 详情" size="70%" @close="handleCloseDetail">
6
+ <el-drawer v-model="detailDrawer.visible" :title="t('system.api.title.detail')" size="70%" @close="handleCloseDetail">
7
7
  <el-descriptions v-if="detailData" :column="1" border>
8
- <el-descriptions-item label="工具名">{{ detailData.tool_name }}</el-descriptions-item>
9
- <el-descriptions-item label="工具提示词">
8
+ <el-descriptions-item :label="t('system.api.field.toolName')">{{ detailData.tool_name }}</el-descriptions-item>
9
+ <el-descriptions-item :label="t('system.api.field.toolPrompts')">
10
10
  <div class="tool-prompts">
11
11
  <el-tag v-for="prompt in detailToolPrompts" :key="prompt" effect="plain">{{ prompt }}</el-tag>
12
12
  <span v-if="!detailToolPrompts.length">--</span>
13
13
  </div>
14
14
  </el-descriptions-item>
15
- <el-descriptions-item label="服务名">{{ detailData.service_name }}</el-descriptions-item>
16
- <el-descriptions-item label="服务描述">{{ detailData.service_desc }}</el-descriptions-item>
17
- <el-descriptions-item label="描述">{{ detailData.desc }}</el-descriptions-item>
18
- <el-descriptions-item label="操作方法">{{ detailData.operation }}</el-descriptions-item>
19
- <el-descriptions-item label="请求方法">{{ detailData.method }}</el-descriptions-item>
20
- <el-descriptions-item label="请求地址">{{ detailData.path }}</el-descriptions-item>
21
- <el-descriptions-item label="MCP工具">{{ formatStatus(detailData.mcp_status) }}</el-descriptions-item>
22
- <el-descriptions-item label="Agent工具">{{ formatStatus(detailData.agent_status) }}</el-descriptions-item>
15
+ <el-descriptions-item :label="t('system.api.field.serviceName')">{{ detailData.service_name }}</el-descriptions-item>
16
+ <el-descriptions-item :label="t('system.api.field.serviceDescription')">{{
17
+ detailData.service_desc
18
+ }}</el-descriptions-item>
19
+ <el-descriptions-item :label="t('system.api.field.description')">{{ detailData.desc }}</el-descriptions-item>
20
+ <el-descriptions-item :label="t('system.api.field.operation')">{{ detailData.operation }}</el-descriptions-item>
21
+ <el-descriptions-item :label="t('system.api.field.method')">{{ detailData.method }}</el-descriptions-item>
22
+ <el-descriptions-item :label="t('system.api.field.path')">{{ detailData.path }}</el-descriptions-item>
23
+ <el-descriptions-item :label="t('system.api.field.mcpTool')">{{
24
+ formatStatus(detailData.mcp_status)
25
+ }}</el-descriptions-item>
26
+ <el-descriptions-item :label="t('system.api.field.agentTool')">{{
27
+ formatStatus(detailData.agent_status)
28
+ }}</el-descriptions-item>
23
29
  </el-descriptions>
24
30
 
25
31
  <div v-if="detailDoc" class="api-doc">
26
32
  <section class="api-doc-section">
27
- <div class="api-doc-title">请求参数</div>
33
+ <div class="api-doc-title">{{ t("system.api.section.parameters") }}</div>
28
34
  <el-table
29
35
  v-if="detailParameters.length > 0"
30
36
  :data="detailParameters"
@@ -32,21 +38,26 @@
32
38
  default-expand-all
33
39
  :tree-props="{ children: 'children' }"
34
40
  >
35
- <el-table-column prop="path" label="字段" min-width="220" />
36
- <el-table-column prop="in" label="位置" width="90" />
37
- <el-table-column label="类型" min-width="180">
41
+ <el-table-column prop="path" :label="t('system.api.doc.field.name')" min-width="220" />
42
+ <el-table-column prop="in" :label="t('system.api.doc.field.location')" width="90" />
43
+ <el-table-column :label="t('system.api.doc.field.type')" min-width="180">
38
44
  <template #default="{ row }">{{ formatSchemaType(row) }}</template>
39
45
  </el-table-column>
40
- <el-table-column label="必填" width="80" align="center">
41
- <template #default="{ row }">{{ row.required ? "是" : "否" }}</template>
46
+ <el-table-column :label="t('system.api.doc.field.required')" width="80" align="center">
47
+ <template #default="{ row }">{{ t(row.required ? "system.common.value.yes" : "system.common.value.no") }}</template>
42
48
  </el-table-column>
43
- <el-table-column prop="description" label="说明" min-width="240" show-overflow-tooltip />
49
+ <el-table-column
50
+ prop="description"
51
+ :label="t('system.api.doc.field.description')"
52
+ min-width="240"
53
+ show-overflow-tooltip
54
+ />
44
55
  </el-table>
45
- <el-empty v-else description="无请求参数" :image-size="72" />
56
+ <el-empty v-else :description="t('system.api.message.noParameters')" :image-size="72" />
46
57
  </section>
47
58
 
48
59
  <section class="api-doc-section">
49
- <div class="api-doc-title">请求体</div>
60
+ <div class="api-doc-title">{{ t("system.api.section.requestBody") }}</div>
50
61
  <el-table
51
62
  v-if="requestBodyRows.length > 0"
52
63
  :data="requestBodyRows"
@@ -54,20 +65,25 @@
54
65
  default-expand-all
55
66
  :tree-props="{ children: 'children' }"
56
67
  >
57
- <el-table-column prop="path" label="字段" min-width="220" />
58
- <el-table-column label="类型" min-width="180">
68
+ <el-table-column prop="path" :label="t('system.api.doc.field.name')" min-width="220" />
69
+ <el-table-column :label="t('system.api.doc.field.type')" min-width="180">
59
70
  <template #default="{ row }">{{ formatSchemaType(row) }}</template>
60
71
  </el-table-column>
61
- <el-table-column label="必填" width="80" align="center">
62
- <template #default="{ row }">{{ row.required ? "是" : "否" }}</template>
72
+ <el-table-column :label="t('system.api.doc.field.required')" width="80" align="center">
73
+ <template #default="{ row }">{{ t(row.required ? "system.common.value.yes" : "system.common.value.no") }}</template>
63
74
  </el-table-column>
64
- <el-table-column prop="description" label="说明" min-width="240" show-overflow-tooltip />
75
+ <el-table-column
76
+ prop="description"
77
+ :label="t('system.api.doc.field.description')"
78
+ min-width="240"
79
+ show-overflow-tooltip
80
+ />
65
81
  </el-table>
66
- <el-empty v-else description="无请求体" :image-size="72" />
82
+ <el-empty v-else :description="t('system.api.message.noRequestBody')" :image-size="72" />
67
83
  </section>
68
84
 
69
85
  <section class="api-doc-section">
70
- <div class="api-doc-title">返回值</div>
86
+ <div class="api-doc-title">{{ t("system.api.section.responses") }}</div>
71
87
  <el-collapse v-if="detailResponses.length > 0">
72
88
  <el-collapse-item v-for="response in detailResponses" :key="response.status" :name="response.status">
73
89
  <template #title>
@@ -80,16 +96,21 @@
80
96
  default-expand-all
81
97
  :tree-props="{ children: 'children' }"
82
98
  >
83
- <el-table-column prop="path" label="字段" min-width="220" />
84
- <el-table-column label="类型" min-width="180">
99
+ <el-table-column prop="path" :label="t('system.api.doc.field.name')" min-width="220" />
100
+ <el-table-column :label="t('system.api.doc.field.type')" min-width="180">
85
101
  <template #default="{ row }">{{ formatSchemaType(row) }}</template>
86
102
  </el-table-column>
87
- <el-table-column prop="description" label="说明" min-width="240" show-overflow-tooltip />
103
+ <el-table-column
104
+ prop="description"
105
+ :label="t('system.api.doc.field.description')"
106
+ min-width="240"
107
+ show-overflow-tooltip
108
+ />
88
109
  </el-table>
89
- <el-empty v-else description="无响应体" :image-size="72" />
110
+ <el-empty v-else :description="t('system.api.message.noResponseBody')" :image-size="72" />
90
111
  </el-collapse-item>
91
112
  </el-collapse>
92
- <el-empty v-else description="无返回值" :image-size="72" />
113
+ <el-empty v-else :description="t('system.api.message.noResponses')" :image-size="72" />
93
114
  </section>
94
115
  </div>
95
116
  </el-drawer>
@@ -97,7 +118,7 @@
97
118
  <FormDialog
98
119
  v-model="editDialog.visible"
99
120
  ref="editDialogRef"
100
- title="编辑API"
121
+ :title="t('system.api.title.edit')"
101
122
  width="760px"
102
123
  :model="editForm"
103
124
  :fields="editFields"
@@ -119,8 +140,15 @@ import type { ProFormField } from "@liujitcn/kratos-admin-core/components/ProFor
119
140
  import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
120
141
  import { defBaseApiService } from "@liujitcn/kratos-admin-system/api/system/base_api";
121
142
  import { Status } from "@liujitcn/kratos-admin-system/rpc/common/v1/enum";
122
- import type { BaseApi, BaseApiDoc, BaseApiDocResponse, BaseApiDocSchema, PageBaseApiRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_api";
143
+ import type {
144
+ BaseApi,
145
+ BaseApiDoc,
146
+ BaseApiDocResponse,
147
+ BaseApiDocSchema,
148
+ PageBaseApiRequest
149
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_api";
123
150
  import { buildPageRequest } from "@liujitcn/kratos-admin-core/table";
151
+ import { t } from "@liujitcn/kratos-admin-core";
124
152
 
125
153
  defineOptions({
126
154
  name: "BaseApi",
@@ -157,95 +185,105 @@ const detailResponses = computed(() => detailDoc.value?.responses ?? []);
157
185
  const detailToolPrompts = computed(() => detailData.value?.tool_prompts ?? []);
158
186
 
159
187
  /** API 编辑表单字段配置。 */
160
- const editFields: ProFormField[] = [
188
+ const editFields = computed<ProFormField[]>(() => [
161
189
  {
162
190
  prop: "tool_name",
163
- label: "工具名",
191
+ label: t("system.api.field.toolName"),
164
192
  component: "input",
165
193
  props: { disabled: true }
166
194
  },
167
195
  {
168
196
  prop: "tool_prompts",
169
- label: "工具提示词",
197
+ label: t("system.api.field.toolPrompts"),
170
198
  component: "dynamic-list",
171
- props: { inputProps: { placeholder: "请输入工具提示词" } }
199
+ props: { inputProps: { placeholder: t("system.api.placeholder.toolPrompt") } }
172
200
  },
173
201
  {
174
202
  prop: "mcp_status",
175
- label: "MCP工具状态",
203
+ label: t("system.api.field.mcpStatus"),
176
204
  component: "switch",
177
- props: { activeValue: Status.ENABLE, inactiveValue: Status.DISABLE, activeText: "启用", inactiveText: "禁用" }
205
+ props: {
206
+ activeValue: Status.ENABLE,
207
+ inactiveValue: Status.DISABLE,
208
+ activeText: t("common.status.enabled"),
209
+ inactiveText: t("common.status.disabled")
210
+ }
178
211
  },
179
212
  {
180
213
  prop: "agent_status",
181
- label: "Agent工具状态",
214
+ label: t("system.api.field.agentStatus"),
182
215
  component: "switch",
183
- props: { activeValue: Status.ENABLE, inactiveValue: Status.DISABLE, activeText: "启用", inactiveText: "禁用" }
216
+ props: {
217
+ activeValue: Status.ENABLE,
218
+ inactiveValue: Status.DISABLE,
219
+ activeText: t("common.status.enabled"),
220
+ inactiveText: t("common.status.disabled")
221
+ }
184
222
  }
185
- ];
223
+ ]);
186
224
 
187
- const statusOptions = [
188
- { label: "启用", value: Status.ENABLE },
189
- { label: "禁用", value: Status.DISABLE }
190
- ];
225
+ const statusOptions = computed(() => [
226
+ { label: t("common.status.enabled"), value: Status.ENABLE },
227
+ { label: t("common.status.disabled"), value: Status.DISABLE }
228
+ ]);
191
229
 
192
230
  /** API 表格列配置。 */
193
- const columns: ColumnProps[] = [
194
- { prop: "tool_name", label: "工具名", minWidth: 260, search: { el: "input" } },
231
+ const columns = computed<ColumnProps[]>(() => [
232
+ { prop: "tool_name", label: t("system.api.field.toolName"), minWidth: 260, search: { el: "input" } },
195
233
  {
196
234
  prop: "tool_prompts",
197
- label: "工具提示词",
235
+ label: t("system.api.field.toolPrompts"),
198
236
  minWidth: 240,
199
237
  search: { el: "input", key: "tool_prompt" },
200
238
  render: scope => formatToolPrompts((scope.row as BaseApi).tool_prompts)
201
239
  },
202
- { prop: "service_name", label: "服务名", minWidth: 180, search: { el: "input" } },
203
- { prop: "service_desc", label: "服务描述", minWidth: 180, search: { el: "input" } },
204
- { prop: "desc", label: "描述", minWidth: 180, search: { el: "input" } },
205
- { prop: "operation", label: "操作方法", minWidth: 260, search: { el: "input" } },
206
- { prop: "method", label: "请求方法", width: 110, search: { el: "input" } },
207
- { prop: "path", label: "请求地址", minWidth: 260, search: { el: "input" } },
240
+ { prop: "service_name", label: t("system.api.field.serviceName"), minWidth: 180, search: { el: "input" } },
241
+ { prop: "service_desc", label: t("system.api.field.serviceDescription"), minWidth: 180, search: { el: "input" } },
242
+ { prop: "desc", label: t("system.api.field.description"), minWidth: 180, search: { el: "input" } },
243
+ { prop: "operation", label: t("system.api.field.operation"), minWidth: 260, search: { el: "input" } },
244
+ { prop: "method", label: t("system.api.field.method"), width: 110, search: { el: "input" } },
245
+ { prop: "path", label: t("system.api.field.path"), minWidth: 260, search: { el: "input" } },
208
246
  {
209
247
  prop: "mcp_status",
210
- label: "MCP工具状态",
248
+ label: t("system.api.field.mcpStatus"),
211
249
  width: 120,
212
- enum: statusOptions,
250
+ enum: statusOptions.value,
213
251
  search: { el: "select" },
214
252
  cellType: "status",
215
253
  statusProps: {
216
254
  activeValue: Status.ENABLE,
217
255
  inactiveValue: Status.DISABLE,
218
- activeText: "启用",
219
- inactiveText: "禁用",
256
+ activeText: t("common.status.enabled"),
257
+ inactiveText: t("common.status.disabled"),
220
258
  disabled: () => !BUTTONS.value["base:api:mcp-status"],
221
259
  beforeChange: scope => handleBeforeSetMcpStatus(scope.row as BaseApi)
222
260
  }
223
261
  },
224
262
  {
225
263
  prop: "agent_status",
226
- label: "Agent工具状态",
264
+ label: t("system.api.field.agentStatus"),
227
265
  width: 130,
228
- enum: statusOptions,
266
+ enum: statusOptions.value,
229
267
  search: { el: "select" },
230
268
  cellType: "status",
231
269
  statusProps: {
232
270
  activeValue: Status.ENABLE,
233
271
  inactiveValue: Status.DISABLE,
234
- activeText: "启用",
235
- inactiveText: "禁用",
272
+ activeText: t("common.status.enabled"),
273
+ inactiveText: t("common.status.disabled"),
236
274
  disabled: () => !BUTTONS.value["base:api:agent-status"],
237
275
  beforeChange: scope => handleBeforeSetAgentStatus(scope.row as BaseApi)
238
276
  }
239
277
  },
240
278
  {
241
279
  prop: "operation",
242
- label: "操作",
280
+ label: t("system.common.field.action"),
243
281
  width: 210,
244
282
  fixed: "right",
245
283
  cellType: "actions",
246
284
  actions: [
247
285
  {
248
- label: "编辑",
286
+ label: t("common.action.edit"),
249
287
  type: "primary",
250
288
  link: true,
251
289
  icon: EditPen,
@@ -253,7 +291,7 @@ const columns: ColumnProps[] = [
253
291
  onClick: scope => handleOpenEditDialog(scope.row as BaseApi)
254
292
  },
255
293
  {
256
- label: "详情",
294
+ label: t("common.action.view"),
257
295
  type: "primary",
258
296
  link: true,
259
297
  icon: View,
@@ -262,7 +300,7 @@ const columns: ColumnProps[] = [
262
300
  }
263
301
  ]
264
302
  }
265
- ];
303
+ ]);
266
304
 
267
305
  /**
268
306
  * 请求 API 分页列表,并由 ProTable 统一维护分页与搜索参数。
@@ -337,7 +375,7 @@ async function handleSubmitEdit() {
337
375
  mcp_status: editForm.mcp_status,
338
376
  agent_status: editForm.agent_status
339
377
  });
340
- ElMessage.success("保存成功");
378
+ ElMessage.success(t("system.api.message.saveSuccess"));
341
379
  handleCloseEditDialog();
342
380
  refreshTable();
343
381
  }
@@ -347,16 +385,16 @@ async function handleSubmitEdit() {
347
385
  */
348
386
  async function handleBeforeSetMcpStatus(row: BaseApi) {
349
387
  const nextStatus = row.mcp_status === Status.ENABLE ? Status.DISABLE : Status.ENABLE;
350
- const text = nextStatus === Status.ENABLE ? "启用" : "禁用";
388
+ const action = t(nextStatus === Status.ENABLE ? "common.status.enabled" : "common.status.disabled");
351
389
  const apiName = row.desc || row.operation || `ID:${row.id}`;
352
390
  try {
353
- await ElMessageBox.confirm(`是否确定${text}该 API 的 MCP 工具能力?\nAPI:${apiName}`, "提示", {
354
- confirmButtonText: "确认",
355
- cancelButtonText: "取消",
391
+ await ElMessageBox.confirm(t("system.api.message.confirmMcpStatus", { action, api: apiName }), t("common.title.notice"), {
392
+ confirmButtonText: t("common.action.confirm"),
393
+ cancelButtonText: t("common.action.cancel"),
356
394
  type: "warning"
357
395
  });
358
396
  await defBaseApiService.SetBaseApiMcpStatus({ id: row.id, mcp_status: nextStatus });
359
- ElMessage.success(`${text}成功`);
397
+ ElMessage.success(t("system.common.message.statusSuccess", { action }));
360
398
  refreshTable();
361
399
  return true;
362
400
  } catch {
@@ -369,16 +407,16 @@ async function handleBeforeSetMcpStatus(row: BaseApi) {
369
407
  */
370
408
  async function handleBeforeSetAgentStatus(row: BaseApi) {
371
409
  const nextStatus = row.agent_status === Status.ENABLE ? Status.DISABLE : Status.ENABLE;
372
- const text = nextStatus === Status.ENABLE ? "启用" : "禁用";
410
+ const action = t(nextStatus === Status.ENABLE ? "common.status.enabled" : "common.status.disabled");
373
411
  const apiName = row.desc || row.operation || `ID:${row.id}`;
374
412
  try {
375
- await ElMessageBox.confirm(`是否确定${text}该 API 的 Agent 工具能力?\nAPI:${apiName}`, "提示", {
376
- confirmButtonText: "确认",
377
- cancelButtonText: "取消",
413
+ await ElMessageBox.confirm(t("system.api.message.confirmAgentStatus", { action, api: apiName }), t("common.title.notice"), {
414
+ confirmButtonText: t("common.action.confirm"),
415
+ cancelButtonText: t("common.action.cancel"),
378
416
  type: "warning"
379
417
  });
380
418
  await defBaseApiService.SetBaseApiAgentStatus({ id: row.id, agent_status: nextStatus });
381
- ElMessage.success(`${text}成功`);
419
+ ElMessage.success(t("system.common.message.statusSuccess", { action }));
382
420
  refreshTable();
383
421
  return true;
384
422
  } catch {
@@ -391,16 +429,16 @@ async function handleBeforeSetAgentStatus(row: BaseApi) {
391
429
  */
392
430
  function formatToolPrompts(prompts: string[]) {
393
431
  if (!prompts?.length) return "--";
394
- return prompts.filter(Boolean).join(";");
432
+ return prompts.filter(Boolean).join(", ");
395
433
  }
396
434
 
397
435
  /**
398
436
  * 格式化 API 工具状态。
399
437
  */
400
438
  function formatStatus(status: Status) {
401
- if (status === Status.ENABLE) return "启用";
402
- if (status === Status.DISABLE) return "禁用";
403
- return "未知";
439
+ if (status === Status.ENABLE) return t("common.status.enabled");
440
+ if (status === Status.DISABLE) return t("common.status.disabled");
441
+ return t("system.common.value.unknown");
404
442
  }
405
443
 
406
444
  /**
@@ -17,7 +17,7 @@
17
17
  <FormDialog
18
18
  v-model="dialog.visible"
19
19
  ref="formDialogRef"
20
- :title="dialog.title"
20
+ :title="t(dialog.titleKey)"
21
21
  width="640px"
22
22
  :model="formData"
23
23
  :fields="formFields"
@@ -44,6 +44,7 @@ import { defBaseAreaService } from "@liujitcn/kratos-admin-system/api/system/bas
44
44
  import type { TreeBaseAreaRequest, BaseArea, BaseAreaForm } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_area";
45
45
 
46
46
  import { normalizeSelectedIds } from "@liujitcn/kratos-admin-core/table";
47
+ import { t } from "@liujitcn/kratos-admin-core";
47
48
 
48
49
  defineOptions({
49
50
  name: "BaseArea",
@@ -55,7 +56,7 @@ const proTable = ref<ProTableInstance>();
55
56
  const formDialogRef = ref<InstanceType<typeof FormDialog>>();
56
57
 
57
58
  const dialog = reactive({
58
- title: "",
59
+ titleKey: "system.area.action.create",
59
60
  visible: false
60
61
  });
61
62
 
@@ -65,10 +66,27 @@ const formData = reactive<BaseAreaForm>({
65
66
  name: ""
66
67
  });
67
68
 
68
- const rules = reactive<FormRules>({
69
- parent_id: [{ required: true, message: "父级区域不能为空", trigger: "change" }],
70
- name: [{ required: true, message: "区域名称不能为空", trigger: "blur" }, { max: 50, message: "区域名称不能超过 50 个字符", trigger: "blur" }]
71
- });
69
+ const rules = computed<FormRules>(() => ({
70
+ parent_id: [
71
+ {
72
+ required: true,
73
+ message: t("system.common.validation.requiredSelect", { field: t("system.area.field.parent") }),
74
+ trigger: "change"
75
+ }
76
+ ],
77
+ name: [
78
+ {
79
+ required: true,
80
+ message: t("system.common.validation.requiredInput", { field: t("system.area.field.name") }),
81
+ trigger: "blur"
82
+ },
83
+ {
84
+ max: 50,
85
+ message: t("system.common.validation.maxLength", { field: t("system.area.field.name"), max: 50 }),
86
+ trigger: "blur"
87
+ }
88
+ ]
89
+ }));
72
90
  const parentIdFormOptions = ref<ProFormOption[]>([]);
73
91
 
74
92
  type GeneratedTreeOption = ProFormOption & {
@@ -85,34 +103,55 @@ function normalizeLazyTreeOptions(options: GeneratedTreeOption[] = []): ProFormO
85
103
  }
86
104
 
87
105
  /** 懒加载parentIdForm树形选项的子节点。 */
88
- async function loadParentIdFormTreeOptions(node: { level: number; value?: string | number; data?: { value?: string | number } }, resolve: (data: ProFormOption[]) => void) {
106
+ async function loadParentIdFormTreeOptions(
107
+ node: { level: number; value?: string | number; data?: { value?: string | number } },
108
+ resolve: (data: ProFormOption[]) => void
109
+ ) {
89
110
  const parentId = node.level === 0 ? 0 : Number(node.data?.value ?? node.value ?? 0);
90
- const response = await defBaseAreaService.OptionBaseArea({ "parent_id": parentId, lazy: true } as Parameters<typeof defBaseAreaService.OptionBaseArea>[0]);
111
+ const response = await defBaseAreaService.OptionBaseArea({ parent_id: parentId, lazy: true } as Parameters<
112
+ typeof defBaseAreaService.OptionBaseArea
113
+ >[0]);
91
114
  resolve(normalizeLazyTreeOptions((response.list ?? []) as GeneratedTreeOption[]));
92
115
  }
93
116
 
94
-
95
117
  void loadFormOptions();
96
118
 
97
119
  /** 行政区域表单字段配置。 */
98
120
  const formFields = computed<ProFormField[]>(() => [
99
- { prop: "parent_id", label: "父级区域", component: "tree-select", options: parentIdFormOptions.value, props: { lazy: true, load: loadParentIdFormTreeOptions, placeholder: "请选择", filterable: true, style: { width: "100%" } } },
100
- { prop: "name", label: "区域名称", component: "input", props: { placeholder: "请输入区域名称" } }
121
+ {
122
+ prop: "parent_id",
123
+ label: t("system.area.field.parent"),
124
+ component: "tree-select",
125
+ options: parentIdFormOptions.value,
126
+ props: {
127
+ lazy: true,
128
+ load: loadParentIdFormTreeOptions,
129
+ placeholder: t("common.placeholder.select"),
130
+ filterable: true,
131
+ style: { width: "100%" }
132
+ }
133
+ },
134
+ {
135
+ prop: "name",
136
+ label: t("system.area.field.name"),
137
+ component: "input",
138
+ props: { placeholder: t("system.common.validation.requiredInput", { field: t("system.area.field.name") }) }
139
+ }
101
140
  ]);
102
141
 
103
142
  /** 行政区域表格列配置。 */
104
143
  const columns = computed<ColumnProps[]>(() => [
105
144
  { type: "selection", width: 55 },
106
- { prop: "name", label: "区域名称", align: "left", search: { el: "input" } },
145
+ { prop: "name", label: t("system.area.field.name"), align: "left", search: { el: "input" } },
107
146
  {
108
147
  prop: "operation",
109
- label: "操作",
148
+ label: t("system.common.field.operation"),
110
149
  width: 150,
111
150
  fixed: "right",
112
151
  cellType: "actions",
113
152
  actions: [
114
153
  {
115
- label: "编辑",
154
+ label: t("common.action.edit"),
116
155
  type: "primary",
117
156
  link: true,
118
157
  icon: EditPen,
@@ -120,7 +159,7 @@ const columns = computed<ColumnProps[]>(() => [
120
159
  onClick: scope => handleOpenDialog((scope.row as BaseArea).id)
121
160
  },
122
161
  {
123
- label: "删除",
162
+ label: t("common.action.delete"),
124
163
  type: "danger",
125
164
  link: true,
126
165
  icon: Delete,
@@ -132,23 +171,23 @@ const columns = computed<ColumnProps[]>(() => [
132
171
  ]);
133
172
 
134
173
  /** 行政区域顶部按钮配置。 */
135
- const headerActions: HeaderActionProps[] = [
174
+ const headerActions = computed<HeaderActionProps[]>(() => [
136
175
  {
137
- label: "新增",
176
+ label: t("common.action.create"),
138
177
  type: "success",
139
178
  icon: CirclePlus,
140
179
  hidden: () => !BUTTONS.value["base:area:create"],
141
180
  onClick: () => handleOpenDialog()
142
181
  },
143
182
  {
144
- label: "删除",
183
+ label: t("common.action.delete"),
145
184
  type: "danger",
146
185
  icon: Delete,
147
186
  hidden: () => !BUTTONS.value["base:area:delete"],
148
187
  disabled: scope => !scope.selectedList.length,
149
188
  onClick: scope => handleDelete(scope.selectedList as BaseArea[])
150
189
  }
151
- ];
190
+ ]);
152
191
 
153
192
  /**
154
193
  * 请求行政区域列表,并适配 ProTable 固定列表字段。
@@ -166,7 +205,7 @@ async function loadAreaChildren(row: BaseArea, _treeNode: unknown, resolve: (dat
166
205
  const data = await defBaseAreaService.TreeBaseArea({ parent_id: row.id, lazy: true });
167
206
  resolve(data.base_areas ?? []);
168
207
  } catch {
169
- ElMessage.error("加载行政区域子节点失败");
208
+ ElMessage.error(t("system.common.message.loadChildrenFailed", { resource: t("system.area.resource") }));
170
209
  resolve([]);
171
210
  }
172
211
  }
@@ -179,8 +218,15 @@ function refreshTable() {
179
218
  }
180
219
  /** 加载表单选择项。 */
181
220
  async function loadFormOptions() {
182
- const parentIdFormResponse = await defBaseAreaService.OptionBaseArea({ "parent_id": 0, lazy: true } as Parameters<typeof defBaseAreaService.OptionBaseArea>[0]);
183
- parentIdFormOptions.value = [{ label: "顶级节点", value: 0 }, ...normalizeLazyTreeOptions((parentIdFormResponse.list ?? []) as GeneratedTreeOption[]).filter(option => Number(option.value) !== 0)];
221
+ const parentIdFormResponse = await defBaseAreaService.OptionBaseArea({ parent_id: 0, lazy: true } as Parameters<
222
+ typeof defBaseAreaService.OptionBaseArea
223
+ >[0]);
224
+ parentIdFormOptions.value = [
225
+ { label: t("system.area.value.root"), value: 0 },
226
+ ...normalizeLazyTreeOptions((parentIdFormResponse.list ?? []) as GeneratedTreeOption[]).filter(
227
+ option => Number(option.value) !== 0
228
+ )
229
+ ];
184
230
  }
185
231
 
186
232
  /**
@@ -189,7 +235,7 @@ async function loadFormOptions() {
189
235
  async function handleOpenDialog(id?: number) {
190
236
  resetForm();
191
237
  await loadFormOptions();
192
- dialog.title = id ? "修改行政区域" : "新增行政区域";
238
+ dialog.titleKey = id ? "system.area.action.edit" : "system.area.action.create";
193
239
  dialog.visible = true;
194
240
  if (!id) return;
195
241
 
@@ -225,7 +271,11 @@ function handleSubmit() {
225
271
  ? defBaseAreaService.UpdateBaseArea({ id: payload.id, base_area: payload })
226
272
  : defBaseAreaService.CreateBaseArea({ base_area: payload });
227
273
  request.then(() => {
228
- ElMessage.success(payload.id ? "修改行政区域成功" : "新增行政区域成功");
274
+ ElMessage.success(
275
+ t(payload.id ? "system.common.message.updateSuccess" : "system.common.message.createSuccess", {
276
+ resource: t("system.area.resource")
277
+ })
278
+ );
229
279
  handleCloseDialog();
230
280
  refreshTable();
231
281
  });
@@ -245,24 +295,24 @@ function handleDelete(selected?: number | string | Array<number | string> | Base
245
295
  rowList.length ? rowList.map(item => item.id) : normalizeSelectedIds(selected as number | string | Array<number | string>)
246
296
  ).join(",");
247
297
  if (!ids) {
248
- ElMessage.warning("请勾选删除项");
298
+ ElMessage.warning(t("system.common.message.selectDeleteItem"));
249
299
  return;
250
300
  }
251
301
 
252
- const confirmMessage = rowList.length === 1 ? "是否确定删除行政区域?" : "确认删除已选中的行政区域吗?";
253
- ElMessageBox.confirm(confirmMessage, "警告", {
254
- confirmButtonText: "确定",
255
- cancelButtonText: "取消",
302
+ const confirmMessage = t(rowList.length === 1 ? "system.area.message.deleteSingle" : "system.area.message.deleteBatch");
303
+ ElMessageBox.confirm(confirmMessage, t("common.title.warning"), {
304
+ confirmButtonText: t("common.action.confirm"),
305
+ cancelButtonText: t("common.action.cancel"),
256
306
  type: "warning"
257
307
  }).then(
258
308
  () => {
259
309
  defBaseAreaService.DeleteBaseArea({ ids }).then(() => {
260
- ElMessage.success("删除行政区域成功");
310
+ ElMessage.success(t("system.common.message.deleteSuccess", { resource: t("system.area.resource") }));
261
311
  refreshTable();
262
312
  });
263
313
  },
264
314
  () => {
265
- ElMessage.info("已取消删除行政区域");
315
+ ElMessage.info(t("system.common.dialog.cancelDelete", { resource: t("system.area.resource") }));
266
316
  }
267
317
  );
268
318
  }