@liujitcn/kratos-admin-system 0.0.20 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +51 -50
  2. package/dist/package/declarations/src/api/system/base_language.d.ts +52 -0
  3. package/dist/package/declarations/src/api/system/base_translation.d.ts +10 -0
  4. package/dist/package/declarations/src/api/system/code_gen_i18n.d.ts +8 -0
  5. package/dist/package/declarations/src/api/system/ops_monitoring.d.ts +19 -0
  6. package/dist/package/declarations/src/api/system/ops_monitoring_sse.d.ts +12 -0
  7. package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +16 -0
  8. package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +20 -0
  9. package/dist/package/declarations/src/components/dynamicTranslation.d.ts +38 -0
  10. package/dist/package/declarations/src/locales/generated.d.ts +6536 -0
  11. package/dist/package/declarations/src/rpc/base/v1/ai_session.d.ts +12 -2
  12. package/dist/package/declarations/src/rpc/base/v1/ai_tool.d.ts +9 -1
  13. package/dist/package/declarations/src/rpc/base/v1/config.d.ts +35 -0
  14. package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +1 -1
  15. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +23 -2
  16. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +9 -0
  17. package/dist/package/declarations/src/rpc/system/admin/v1/base_job.d.ts +9 -1
  18. package/dist/package/declarations/src/rpc/system/admin/v1/base_language.d.ts +119 -0
  19. package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +6 -1
  20. package/dist/package/declarations/src/rpc/system/admin/v1/base_migration.d.ts +6 -6
  21. package/dist/package/declarations/src/rpc/system/admin/v1/base_role.d.ts +13 -1
  22. package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +75 -0
  23. package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +11 -1
  24. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +13 -11
  25. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_column.d.ts +7 -0
  26. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_table.d.ts +24 -1
  27. package/dist/package/declarations/src/rpc/system/admin/v1/common.d.ts +13 -0
  28. package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +222 -0
  29. package/dist/package/declarations/src/views/base/language/index.vue.d.ts +3 -0
  30. package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue.d.ts +23 -0
  31. package/dist/package/declarations/src/views/tool/code-gen/config.d.ts +7 -7
  32. package/dist/package/declarations/src/views/tool/ops-monitoring/index.vue.d.ts +3 -0
  33. package/dist/package/src/api/base/ai_message.ts +7 -12
  34. package/dist/package/src/api/base/sse.ts +3 -1
  35. package/dist/package/src/api/system/base_language.ts +135 -0
  36. package/dist/package/src/api/system/base_translation.ts +33 -0
  37. package/dist/package/src/api/system/code_gen_column.ts +17 -3
  38. package/dist/package/src/api/system/code_gen_i18n.ts +18 -0
  39. package/dist/package/src/api/system/code_gen_table.ts +12 -4
  40. package/dist/package/src/api/system/ops_monitoring.ts +88 -0
  41. package/dist/package/src/api/system/ops_monitoring_sse.ts +49 -0
  42. package/dist/package/src/components/DynamicTranslationCell.vue +249 -0
  43. package/dist/package/src/components/DynamicTranslationEditor.vue +197 -0
  44. package/dist/package/src/components/dynamicTranslation.ts +66 -0
  45. package/dist/package/src/locales/README.md +30 -0
  46. package/dist/package/src/locales/en-US.json +933 -0
  47. package/dist/package/src/locales/es-ES.json +933 -0
  48. package/dist/package/src/locales/fr-FR.json +933 -0
  49. package/dist/package/src/locales/generated.ts +22 -0
  50. package/dist/package/src/locales/ja-JP.json +933 -0
  51. package/dist/package/src/locales/ko-KR.json +933 -0
  52. package/dist/package/src/locales/zh-CN.json +933 -0
  53. package/dist/package/src/locales/zh-TW.json +933 -0
  54. package/dist/package/src/module.ts +6 -2
  55. package/dist/package/src/rpc/base/v1/ai_session.ts +13 -2
  56. package/dist/package/src/rpc/base/v1/ai_tool.ts +10 -1
  57. package/dist/package/src/rpc/base/v1/config.ts +47 -0
  58. package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
  59. package/dist/package/src/rpc/system/admin/v1/base_config.ts +24 -2
  60. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +9 -0
  61. package/dist/package/src/rpc/system/admin/v1/base_job.ts +10 -1
  62. package/dist/package/src/rpc/system/admin/v1/base_language.ts +141 -0
  63. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +6 -1
  64. package/dist/package/src/rpc/system/admin/v1/base_migration.ts +8 -8
  65. package/dist/package/src/rpc/system/admin/v1/base_role.ts +14 -1
  66. package/dist/package/src/rpc/system/admin/v1/base_translation.ts +90 -0
  67. package/dist/package/src/rpc/system/admin/v1/base_user.ts +12 -1
  68. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +16 -12
  69. package/dist/package/src/rpc/system/admin/v1/code_gen_column.ts +8 -0
  70. package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +27 -1
  71. package/dist/package/src/rpc/system/admin/v1/common.ts +21 -0
  72. package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +255 -0
  73. package/dist/package/src/views/ai/chat/components/AiMarkdown.vue +1 -6
  74. package/dist/package/src/views/ai/chat/components/ChatPanel.vue +75 -58
  75. package/dist/package/src/views/ai/chat/components/SessionPanel.vue +20 -9
  76. package/dist/package/src/views/ai/chat/components/XSender.vue +36 -23
  77. package/dist/package/src/views/ai/chat/index.vue +58 -41
  78. package/dist/package/src/views/ai/chat/message.ts +29 -27
  79. package/dist/package/src/views/base/api/index.vue +121 -84
  80. package/dist/package/src/views/base/area/index.vue +81 -32
  81. package/dist/package/src/views/base/config/index.vue +300 -96
  82. package/dist/package/src/views/base/dept/index.vue +110 -62
  83. package/dist/package/src/views/base/dict/index.vue +145 -62
  84. package/dist/package/src/views/base/dict/item.vue +155 -64
  85. package/dist/package/src/views/base/job/index.vue +134 -82
  86. package/dist/package/src/views/base/job/log.vue +24 -25
  87. package/dist/package/src/views/base/language/index.vue +260 -0
  88. package/dist/package/src/views/base/log/index.vue +68 -46
  89. package/dist/package/src/views/base/menu/index.vue +344 -200
  90. package/dist/package/src/views/base/migration/index.vue +49 -29
  91. package/dist/package/src/views/base/post/index.vue +128 -60
  92. package/dist/package/src/views/base/role/index.vue +145 -79
  93. package/dist/package/src/views/base/tenant/index.vue +132 -64
  94. package/dist/package/src/views/base/user/components/dept-tree.vue +2 -1
  95. package/dist/package/src/views/base/user/index.vue +194 -116
  96. package/dist/package/src/views/profile/components/base.vue +45 -28
  97. package/dist/package/src/views/profile/components/password.vue +45 -30
  98. package/dist/package/src/views/profile/components/security.vue +90 -54
  99. package/dist/package/src/views/profile/index.vue +10 -9
  100. package/dist/package/src/views/tool/api-doc/index.vue +6 -2
  101. package/dist/package/src/views/tool/code-gen/code-preview/index.vue +32 -16
  102. package/dist/package/src/views/tool/code-gen/columns/index.vue +382 -273
  103. package/dist/package/src/views/tool/code-gen/columns/option-copy.ts +1 -6
  104. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +118 -0
  105. package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +65 -36
  106. package/dist/package/src/views/tool/code-gen/components/CodePreviewPane.vue +8 -5
  107. package/dist/package/src/views/tool/code-gen/config.ts +116 -79
  108. package/dist/package/src/views/tool/code-gen/preview/data.ts +19 -17
  109. package/dist/package/src/views/tool/code-gen/preview/index.vue +96 -59
  110. package/dist/package/src/views/tool/code-gen/proto/index.vue +110 -62
  111. package/dist/package/src/views/tool/code-gen/table/index.vue +201 -121
  112. package/dist/package/src/views/tool/ops-monitoring/index.vue +1175 -0
  113. package/dist/package/src/views/tool/project-doc/index.vue +17 -15
  114. package/package.json +6 -2
  115. package/dist/package/declarations/src/rpc/base/v1/enum.d.ts +0 -43
  116. package/dist/package/declarations/src/rpc/system/common/v1/enum.d.ts +0 -67
  117. package/dist/package/src/rpc/base/v1/enum.ts +0 -54
  118. package/dist/package/src/rpc/system/common/v1/enum.ts +0 -80
@@ -11,10 +11,15 @@
11
11
  @toggle-collapse="toggleSessionPanel"
12
12
  />
13
13
  <div v-else class="agent-session-collapsed">
14
- <button class="agent-session-collapsed__toggle" type="button" aria-label="展开会话栏" @click="toggleSessionPanel">
14
+ <button
15
+ class="agent-session-collapsed__toggle"
16
+ type="button"
17
+ :aria-label="t('system.ai.chat.action.expand_sessions')"
18
+ @click="toggleSessionPanel"
19
+ >
15
20
  <el-icon><DArrowRight /></el-icon>
16
21
  </button>
17
- <span class="agent-session-collapsed__label">最近对话</span>
22
+ <span class="agent-session-collapsed__label">{{ t("system.ai.chat.title.recent_conversations") }}</span>
18
23
  </div>
19
24
  <ChatPanel
20
25
  :active-session="activeSession"
@@ -44,6 +49,7 @@ import "vue-element-plus-x/styles/index.css";
44
49
  import { computed, onBeforeUnmount, onMounted, ref } from "vue";
45
50
  import { DArrowRight } from "@element-plus/icons-vue";
46
51
  import { ElMessage, ElMessageBox } from "element-plus";
52
+ import { getCurrentLocale, t } from "@liujitcn/kratos-admin-core";
47
53
  import { getAdminAiExtension } from "@liujitcn/kratos-admin-system";
48
54
  import { defAiMessageService } from "@liujitcn/kratos-admin-system/api/base/ai_message";
49
55
  import { defAiSessionService } from "@liujitcn/kratos-admin-system/api/base/ai_session";
@@ -51,7 +57,8 @@ import { defAiToolService } from "@liujitcn/kratos-admin-system/api/base/ai_tool
51
57
  import type { AiAction } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_message";
52
58
  import type { AiSession } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
53
59
  import type { AiShortcut } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
54
- import { AiMessageStatus, Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/enum";
60
+ import { AiMessageStatus } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
61
+ import { Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
55
62
  import ChatPanel from "./components/ChatPanel.vue";
56
63
  import SessionPanel from "./components/SessionPanel.vue";
57
64
  import {
@@ -145,7 +152,7 @@ async function handleSessionAction(payload: { action: SessionAction; item: AiSes
145
152
  await handleDeleteSession(payload.item);
146
153
  } catch (error) {
147
154
  if (error === "cancel" || error === "close") {
148
- ElMessage.info("已取消操作");
155
+ ElMessage.info(t("system.ai.chat.message.action_canceled"));
149
156
  }
150
157
  }
151
158
  }
@@ -156,7 +163,7 @@ async function handleCreateSession() {
156
163
  if (!sessionID) return;
157
164
  activeSessionID.value = sessionID;
158
165
  messages.value[sessionID] = [];
159
- ElMessage.success("已创建新会话");
166
+ ElMessage.success(t("system.ai.chat.message.conversation_created"));
160
167
  }
161
168
 
162
169
  /** 提交用户输入并同步消息流。 */
@@ -169,7 +176,7 @@ async function handleFlowAction(action: AiAction, label?: string) {
169
176
  const sessionID = activeSessionID.value;
170
177
  if (!sessionID || isSessionSending(sessionID)) return;
171
178
  await sendAiPayload({
172
- text: label || "继续",
179
+ text: label || t("system.ai.chat.action.continue"),
173
180
  attachments: [],
174
181
  action
175
182
  });
@@ -220,7 +227,7 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
220
227
  );
221
228
 
222
229
  if (!response.body) {
223
- throw new Error("AI 助手流式响应为空");
230
+ throw new Error(t("system.ai.chat.message.empty_stream"));
224
231
  }
225
232
  await readAiEventStream(
226
233
  response.body,
@@ -230,14 +237,14 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
230
237
  controller.signal
231
238
  );
232
239
  if (!task.finished && !controller.signal.aborted) {
233
- throw new Error("AI 助手流式响应未完整返回");
240
+ throw new Error(t("system.ai.chat.message.incomplete_stream"));
234
241
  }
235
242
  } catch (error) {
236
243
  if (controller.signal.aborted) return;
237
244
  messages.value[sessionID] = markThinkingMessageFailed(messages.value[sessionID] ?? [], {
238
245
  sessionID
239
246
  });
240
- const message = error instanceof Error ? error.message : "AI 助手请求失败";
247
+ const message = error instanceof Error ? error.message : t("system.ai.chat.message.request_failed");
241
248
  ElMessage.error(message);
242
249
  } finally {
243
250
  if (runningStreamTaskMap.get(sessionID) === task) {
@@ -299,10 +306,10 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
299
306
  const currentMessages = messages.value[sessionID] ?? [];
300
307
  messages.value[sessionID] = replacePendingMessages(currentMessages, normalizeMessageList(response.messages));
301
308
  if (response.session) upsertSession(normalizeSession(response.session));
302
- ElMessage.success("已更新并重新生成");
309
+ ElMessage.success(t("system.ai.chat.message.updated_and_regenerated"));
303
310
  } catch (error) {
304
311
  await loadMessages(sessionID, { force: true });
305
- const message = error instanceof Error ? error.message : "更新消息失败";
312
+ const message = error instanceof Error ? error.message : t("system.ai.chat.message.update_failed");
306
313
  ElMessage.error(message);
307
314
  } finally {
308
315
  setSessionSending(sessionID, false);
@@ -313,9 +320,9 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
313
320
  async function handleCopyMessage(item: ChatMessageItem) {
314
321
  try {
315
322
  await navigator.clipboard.writeText(String(item.content ?? ""));
316
- ElMessage.success("消息已复制");
323
+ ElMessage.success(t("system.ai.chat.message.message_copied"));
317
324
  } catch {
318
- ElMessage.error("当前浏览器不支持复制");
325
+ ElMessage.error(t("system.ai.chat.message.copy_unsupported"));
319
326
  }
320
327
  }
321
328
 
@@ -332,7 +339,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
332
339
  if (item.role === "user") return !message.localOnly;
333
340
  return resolveMessageBubbleKey(message) !== messageKey;
334
341
  });
335
- ElMessage.success("消息已删除");
342
+ ElMessage.success(t("system.ai.chat.message.message_deleted"));
336
343
  return;
337
344
  }
338
345
  await defAiMessageService.DeleteAiMessage({
@@ -340,7 +347,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
340
347
  message_id: String(item.id)
341
348
  });
342
349
  messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => String(message.id) !== String(item.id));
343
- ElMessage.success("消息已删除");
350
+ ElMessage.success(t("system.ai.chat.message.message_deleted"));
344
351
  }
345
352
 
346
353
  /** 重试失败的一轮消息,或重新生成助手输出。 */
@@ -353,19 +360,19 @@ async function handleRetryMessage(item: ChatMessageItem) {
353
360
  if (item.localOnly) {
354
361
  const payload = resolveLocalRetryPayload(item);
355
362
  if (!payload) {
356
- ElMessage.warning("未找到可重新发送的本地消息");
363
+ ElMessage.warning(t("system.ai.chat.message.local_retry_missing"));
357
364
  return;
358
365
  }
359
366
  messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => !message.localOnly);
360
367
  if (await sendAiPayload(payload)) {
361
- ElMessage.success("已重新发送");
368
+ ElMessage.success(t("system.ai.chat.message.resent"));
362
369
  }
363
370
  return;
364
371
  }
365
372
  setSessionSending(sessionID, true);
366
373
  if (item.role === "user") {
367
- if (item.status !== AiMessageStatus.FAILED_AMS) {
368
- ElMessage.warning("只有发送失败的消息可以重新发送");
374
+ if (item.status !== AiMessageStatus.AI_MESSAGE_STATUS_FAILED) {
375
+ ElMessage.warning(t("system.ai.chat.message.retry_failed_only"));
369
376
  return;
370
377
  }
371
378
  response = await defAiMessageService.RetryAiUserMessage({
@@ -382,10 +389,10 @@ async function handleRetryMessage(item: ChatMessageItem) {
382
389
  const current = messages.value[sessionID] ?? [];
383
390
  messages.value[sessionID] = replacePendingMessages(current, normalizeMessageList(response.messages));
384
391
  if (response.session) upsertSession(normalizeSession(response.session));
385
- ElMessage.success(item.role === "user" ? "已重新发送" : "已重新生成");
392
+ ElMessage.success(item.role === "user" ? t("system.ai.chat.message.resent") : t("system.ai.chat.message.regenerated"));
386
393
  } catch (error) {
387
394
  if (item.role !== "user") await loadMessages(sessionID, { force: true });
388
- const message = error instanceof Error ? error.message : "重新生成失败";
395
+ const message = error instanceof Error ? error.message : t("system.ai.chat.message.regenerate_failed");
389
396
  ElMessage.error(message);
390
397
  } finally {
391
398
  if (!item.localOnly) {
@@ -433,14 +440,14 @@ async function handleBranchMessage(item: ChatMessageItem) {
433
440
  upsertSession(branchSession);
434
441
  messages.value[branchSession.id] = normalizeMessageList(response.messages);
435
442
  activeSessionID.value = branchSession.id;
436
- ElMessage.success("已创建分支会话");
443
+ ElMessage.success(t("system.ai.chat.message.branch_created"));
437
444
  }
438
445
 
439
446
  /** 朗读或停止朗读当前助手输出。 */
440
447
  function handleSpeakMessage(item: ChatMessageItem) {
441
448
  if (item.role === "user") return;
442
449
  if (!window.speechSynthesis) {
443
- ElMessage.warning("当前浏览器不支持朗读");
450
+ ElMessage.warning(t("system.ai.chat.message.speech_unsupported"));
444
451
  return;
445
452
  }
446
453
  const messageKey = resolveMessageBubbleKey(item);
@@ -450,7 +457,7 @@ function handleSpeakMessage(item: ChatMessageItem) {
450
457
  }
451
458
  stopSpeaking();
452
459
  const utterance = new SpeechSynthesisUtterance(String(item.content ?? ""));
453
- utterance.lang = "zh-CN";
460
+ utterance.lang = getCurrentLocale();
454
461
  utterance.onend = () => clearSpeakingState(messageKey);
455
462
  utterance.onerror = () => clearSpeakingState(messageKey);
456
463
  speakingMessageID = messageKey;
@@ -665,26 +672,34 @@ async function loadMessages(sessionID: string, options?: { force?: boolean }) {
665
672
 
666
673
  /** 重命名当前会话。 */
667
674
  async function handleRenameSession(item: AiSession) {
668
- const { value } = await ElMessageBox.prompt(`请输入新的会话名称\n当前名称:${item.title}`, "重命名会话", {
669
- confirmButtonText: "确认",
670
- cancelButtonText: "取消",
671
- inputValue: item.title,
672
- inputPattern: /\S+/,
673
- inputErrorMessage: "请输入会话名称"
674
- });
675
+ const { value } = await ElMessageBox.prompt(
676
+ t("system.ai.chat.dialog.rename_description", { title: item.title }),
677
+ t("system.ai.chat.dialog.rename_title"),
678
+ {
679
+ confirmButtonText: t("common.action.confirm"),
680
+ cancelButtonText: t("common.action.cancel"),
681
+ inputValue: item.title,
682
+ inputPattern: /\S+/,
683
+ inputErrorMessage: t("system.ai.chat.placeholder.conversation_name")
684
+ }
685
+ );
675
686
 
676
687
  const response = await defAiSessionService.UpdateAiSession({ id: item.id, title: value.trim() });
677
688
  upsertSession(normalizeSession(response.session));
678
- ElMessage.success("会话已重命名");
689
+ ElMessage.success(t("system.ai.chat.message.conversation_renamed"));
679
690
  }
680
691
 
681
692
  /** 删除当前会话,并自动切换到剩余会话。 */
682
693
  async function handleDeleteSession(item: AiSession) {
683
- await ElMessageBox.confirm(`是否删除该会话?\n会话名称:${item.title}`, "删除会话", {
684
- confirmButtonText: "确认删除",
685
- cancelButtonText: "取消",
686
- type: "warning"
687
- });
694
+ await ElMessageBox.confirm(
695
+ t("system.ai.chat.dialog.delete_description", { title: item.title }),
696
+ t("system.ai.chat.dialog.delete_title"),
697
+ {
698
+ confirmButtonText: t("system.ai.chat.action.confirm_delete_conversation"),
699
+ cancelButtonText: t("common.action.cancel"),
700
+ type: "warning"
701
+ }
702
+ );
688
703
 
689
704
  await defAiSessionService.DeleteAiSession({ id: item.id });
690
705
  cancelSessionStreamTask(item.id);
@@ -697,7 +712,7 @@ async function handleDeleteSession(item: AiSession) {
697
712
  const nextSessionID = await ensureActiveSession();
698
713
  if (nextSessionID) await loadMessages(nextSessionID);
699
714
 
700
- ElMessage.success("会话已删除");
715
+ ElMessage.success(t("system.ai.chat.message.conversation_deleted"));
701
716
  }
702
717
 
703
718
  /** 保证当前存在可用会话;当列表为空时自动创建首个会话。 */
@@ -714,7 +729,7 @@ async function ensureActiveSession() {
714
729
  /** 创建新的助手会话,并同步到本地列表。 */
715
730
  async function createSession(options?: { title?: string }) {
716
731
  const response = await defAiSessionService.CreateAiSession({
717
- title: options?.title || "新对话",
732
+ title: options?.title || t("system.ai.chat.value.new_conversation"),
718
733
  terminal: Terminal.TERMINAL_ADMIN
719
734
  });
720
735
  const normalizedSession = normalizeSession(response.session);
@@ -724,10 +739,12 @@ async function createSession(options?: { title?: string }) {
724
739
 
725
740
  /** 使用当前消息内容生成一个易识别的分支会话标题。 */
726
741
  function buildBranchSessionTitle(item: ChatMessageItem) {
727
- const content = String(item.input_content?.content || item.content || "新对话")
742
+ const content = String(item.input_content?.content || item.content || t("system.ai.chat.value.new_conversation"))
728
743
  .replace(/\s+/g, " ")
729
744
  .trim();
730
- return `分支:${content.slice(0, 18) || "新对话"}`;
745
+ return t("system.ai.chat.value.branch_title", {
746
+ title: content.slice(0, 18) || t("system.ai.chat.value.new_conversation")
747
+ });
731
748
  }
732
749
 
733
750
  /** 归一化快捷入口,保证空态展示稳定排序。 */
@@ -7,13 +7,15 @@ import {
7
7
  type AiToken
8
8
  } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
9
9
  import type { AiAction } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_message";
10
- import { AiMessageStatus, Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/enum";
10
+ import { AiMessageStatus } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
11
+ import { Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
12
+ import { t } from "@liujitcn/kratos-admin-core";
11
13
  import type { AiStreamPayload, AIFlowBlock, ChatMessageItem, ReplySourceTag } from "./types";
12
14
 
13
15
  const THINKING_MESSAGE_ID_PREFIX = "ai-thinking";
14
16
  const LOCAL_USER_MESSAGE_ID_PREFIX = "ai-user-local";
15
17
  const PENDING_STREAM_MESSAGE_ID = "pending";
16
- const THINKING_MESSAGE_CONTENT = "正在整理回复";
18
+ const thinkingMessageContent = () => t("system.ai.chat.message.thinking");
17
19
 
18
20
  /** 生成流式消息分组键,确保同一轮回复只更新当前占位气泡。 */
19
21
  export function buildStreamMessageKey(sessionID: string, messageID: string) {
@@ -42,7 +44,7 @@ export function resolveTimestamp(timestamp?: { seconds?: number; nanos?: number
42
44
  export function normalizeSession(session?: Partial<AiSession> | null): AiSession {
43
45
  return {
44
46
  id: String(session?.id ?? ""),
45
- title: String(session?.title ?? "新对话"),
47
+ title: String(session?.title ?? t("system.ai.chat.value.new_conversation")),
46
48
  summary: String(session?.summary ?? ""),
47
49
  updated_at: session?.updated_at,
48
50
  terminal: Number(session?.terminal ?? Terminal.TERMINAL_ADMIN)
@@ -60,16 +62,16 @@ export function resolveReplySourceTag(
60
62
  item: Pick<ChatMessageItem, "role" | "fallback" | "reply_source" | "model">
61
63
  ): ReplySourceTag | undefined {
62
64
  if (item.role === "user") return undefined;
63
- if (item.fallback) return { text: "降级回复", tone: "warning" };
65
+ if (item.fallback) return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
64
66
  switch (String(item.reply_source ?? "")) {
65
67
  case "network":
66
- return { text: "网络数据", tone: "success" };
68
+ return { text: t("system.ai.chat.source.network"), tone: "success" };
67
69
  case "llm":
68
- return { text: "模型回答", tone: "primary" };
70
+ return { text: t("system.ai.chat.source.model"), tone: "primary" };
69
71
  case "fallback":
70
- return { text: "降级回复", tone: "warning" };
72
+ return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
71
73
  default:
72
- return item.model ? { text: "模型回答", tone: "primary" } : undefined;
74
+ return item.model ? { text: t("system.ai.chat.source.model"), tone: "primary" } : undefined;
73
75
  }
74
76
  }
75
77
 
@@ -168,17 +170,17 @@ export function mapMessageItem(message: AiMessage, role: "user" | "ai"): ChatMes
168
170
  step: role === "ai" ? outputContent.step : "",
169
171
  blocksJson: role === "ai" ? outputContent.blocks_json : "",
170
172
  blocks: role === "ai" ? markFlowBlocksDisabled(parseFlowBlocks(outputContent.blocks_json), String(message.id ?? "")) : [],
171
- status: Number(message.status ?? AiMessageStatus.SUCCESS_AMS),
173
+ status: Number(message.status ?? AiMessageStatus.AI_MESSAGE_STATUS_SUCCESS),
172
174
  token: normalizeToken(message.token),
173
175
  tools: Array.isArray(message.tools) ? message.tools : [],
174
176
  variant: role === "user" ? "filled" : "borderless",
175
177
  shape: "corner",
176
178
  progressState:
177
- message.status === AiMessageStatus.GENERATING_AMS
179
+ message.status === AiMessageStatus.AI_MESSAGE_STATUS_GENERATING
178
180
  ? role === "user"
179
181
  ? "idle"
180
182
  : "streaming"
181
- : message.status === AiMessageStatus.FAILED_AMS
183
+ : message.status === AiMessageStatus.AI_MESSAGE_STATUS_FAILED
182
184
  ? "failed"
183
185
  : "idle",
184
186
  maxWidth: role === "user" ? "380px" : "100%"
@@ -209,7 +211,7 @@ export function createLocalUserMessage(payload: { text: string; attachments: AiA
209
211
  seconds: Math.floor(now.getTime() / 1000),
210
212
  nanos: (now.getTime() % 1000) * 1_000_000
211
213
  },
212
- status: AiMessageStatus.GENERATING_AMS,
214
+ status: AiMessageStatus.AI_MESSAGE_STATUS_GENERATING,
213
215
  token: normalizeToken(),
214
216
  tools: [],
215
217
  first_token_ms: 0,
@@ -236,7 +238,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
236
238
  input_content: undefined,
237
239
  output_content: {
238
240
  kind: "text",
239
- content: THINKING_MESSAGE_CONTENT,
241
+ content: thinkingMessageContent(),
240
242
  reply_source: "",
241
243
  model: "",
242
244
  fallback: false,
@@ -250,7 +252,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
250
252
  seconds: Math.floor(now.getTime() / 1000),
251
253
  nanos: (now.getTime() % 1000) * 1_000_000
252
254
  },
253
- status: AiMessageStatus.GENERATING_AMS,
255
+ status: AiMessageStatus.AI_MESSAGE_STATUS_GENERATING,
254
256
  token: normalizeToken(),
255
257
  tools: [],
256
258
  first_token_ms: 0,
@@ -261,7 +263,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
261
263
  message.progressState = "streaming";
262
264
  message.localOnly = true;
263
265
  message.streamKey = streamKey;
264
- message.replySourceTag = { text: "思考中", tone: "info" };
266
+ message.replySourceTag = { text: t("system.ai.chat.status.thinking"), tone: "info" };
265
267
  return message;
266
268
  }
267
269
 
@@ -290,7 +292,7 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
290
292
  if (String(item.id) !== messageID || item.role === "user") return item;
291
293
  return {
292
294
  ...item,
293
- content: THINKING_MESSAGE_CONTENT,
295
+ content: thinkingMessageContent(),
294
296
  fallback: false,
295
297
  fallback_reason: "",
296
298
  token: normalizeToken(),
@@ -298,8 +300,8 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
298
300
  first_token_ms: 0,
299
301
  duration_ms: 0,
300
302
  progressState: "streaming",
301
- replySourceTag: { text: "思考中", tone: "info" },
302
- status: AiMessageStatus.GENERATING_AMS,
303
+ replySourceTag: { text: t("system.ai.chat.status.thinking"), tone: "info" },
304
+ status: AiMessageStatus.AI_MESSAGE_STATUS_GENERATING,
303
305
  streamKey
304
306
  };
305
307
  });
@@ -354,16 +356,16 @@ export function markThinkingMessageFailed(current: ChatMessageItem[], options?:
354
356
  return {
355
357
  ...item,
356
358
  progressState: "failed",
357
- status: AiMessageStatus.FAILED_AMS
359
+ status: AiMessageStatus.AI_MESSAGE_STATUS_FAILED
358
360
  };
359
361
  }
360
362
  if (item.progressState !== "streaming") return item;
361
363
  return {
362
364
  ...item,
363
365
  progressState: "failed",
364
- status: AiMessageStatus.FAILED_AMS,
365
- content: "这次回复没有成功返回,你可以直接重试刚才的问题。",
366
- replySourceTag: { text: "发送失败", tone: "warning" }
366
+ status: AiMessageStatus.AI_MESSAGE_STATUS_FAILED,
367
+ content: t("system.ai.chat.message.reply_failed"),
368
+ replySourceTag: { text: t("system.ai.chat.status.send_failed"), tone: "warning" }
367
369
  };
368
370
  });
369
371
  }
@@ -379,13 +381,13 @@ export function appendStreamingDelta(current: ChatMessageItem[], payload: AiStre
379
381
  const streamKey = buildStreamMessageKey(String(payload.session_id ?? ""), String(payload.message_id ?? ""));
380
382
  return current.map<ChatMessageItem>(item => {
381
383
  if (item.streamKey !== streamKey || (!item.localOnly && item.role === "user")) return item;
382
- const baseContent = item.content === THINKING_MESSAGE_CONTENT ? "" : item.content;
384
+ const baseContent = item.content === thinkingMessageContent() ? "" : item.content;
383
385
  const nextContent = `${baseContent}${payload.delta ?? ""}`;
384
386
  return {
385
387
  ...item,
386
388
  content: nextContent || item.content,
387
389
  progressState: "streaming",
388
- replySourceTag: { text: "回答中", tone: "info" }
390
+ replySourceTag: { text: t("system.ai.chat.status.answering"), tone: "info" }
389
391
  };
390
392
  });
391
393
  }
@@ -400,9 +402,9 @@ export function markStreamingError(current: ChatMessageItem[], payload: AiStream
400
402
  return {
401
403
  ...item,
402
404
  progressState: "failed",
403
- status: AiMessageStatus.FAILED_AMS,
404
- content: "这次回复没有成功返回,你可以直接重试刚才的问题。",
405
- replySourceTag: { text: "发送失败", tone: "warning" }
405
+ status: AiMessageStatus.AI_MESSAGE_STATUS_FAILED,
406
+ content: t("system.ai.chat.message.reply_failed"),
407
+ replySourceTag: { text: t("system.ai.chat.status.send_failed"), tone: "warning" }
406
408
  };
407
409
  });
408
410
  }