@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
@@ -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.expandSessions')"
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.recentConversations") }}</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";
@@ -145,7 +151,7 @@ async function handleSessionAction(payload: { action: SessionAction; item: AiSes
145
151
  await handleDeleteSession(payload.item);
146
152
  } catch (error) {
147
153
  if (error === "cancel" || error === "close") {
148
- ElMessage.info("已取消操作");
154
+ ElMessage.info(t("system.ai.chat.message.actionCanceled"));
149
155
  }
150
156
  }
151
157
  }
@@ -156,7 +162,7 @@ async function handleCreateSession() {
156
162
  if (!sessionID) return;
157
163
  activeSessionID.value = sessionID;
158
164
  messages.value[sessionID] = [];
159
- ElMessage.success("已创建新会话");
165
+ ElMessage.success(t("system.ai.chat.message.conversationCreated"));
160
166
  }
161
167
 
162
168
  /** 提交用户输入并同步消息流。 */
@@ -169,7 +175,7 @@ async function handleFlowAction(action: AiAction, label?: string) {
169
175
  const sessionID = activeSessionID.value;
170
176
  if (!sessionID || isSessionSending(sessionID)) return;
171
177
  await sendAiPayload({
172
- text: label || "继续",
178
+ text: label || t("system.ai.chat.action.continue"),
173
179
  attachments: [],
174
180
  action
175
181
  });
@@ -220,7 +226,7 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
220
226
  );
221
227
 
222
228
  if (!response.body) {
223
- throw new Error("AI 助手流式响应为空");
229
+ throw new Error(t("system.ai.chat.message.emptyStream"));
224
230
  }
225
231
  await readAiEventStream(
226
232
  response.body,
@@ -230,14 +236,14 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
230
236
  controller.signal
231
237
  );
232
238
  if (!task.finished && !controller.signal.aborted) {
233
- throw new Error("AI 助手流式响应未完整返回");
239
+ throw new Error(t("system.ai.chat.message.incompleteStream"));
234
240
  }
235
241
  } catch (error) {
236
242
  if (controller.signal.aborted) return;
237
243
  messages.value[sessionID] = markThinkingMessageFailed(messages.value[sessionID] ?? [], {
238
244
  sessionID
239
245
  });
240
- const message = error instanceof Error ? error.message : "AI 助手请求失败";
246
+ const message = error instanceof Error ? error.message : t("system.ai.chat.message.requestFailed");
241
247
  ElMessage.error(message);
242
248
  } finally {
243
249
  if (runningStreamTaskMap.get(sessionID) === task) {
@@ -299,10 +305,10 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
299
305
  const currentMessages = messages.value[sessionID] ?? [];
300
306
  messages.value[sessionID] = replacePendingMessages(currentMessages, normalizeMessageList(response.messages));
301
307
  if (response.session) upsertSession(normalizeSession(response.session));
302
- ElMessage.success("已更新并重新生成");
308
+ ElMessage.success(t("system.ai.chat.message.updatedAndRegenerated"));
303
309
  } catch (error) {
304
310
  await loadMessages(sessionID, { force: true });
305
- const message = error instanceof Error ? error.message : "更新消息失败";
311
+ const message = error instanceof Error ? error.message : t("system.ai.chat.message.updateFailed");
306
312
  ElMessage.error(message);
307
313
  } finally {
308
314
  setSessionSending(sessionID, false);
@@ -313,9 +319,9 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
313
319
  async function handleCopyMessage(item: ChatMessageItem) {
314
320
  try {
315
321
  await navigator.clipboard.writeText(String(item.content ?? ""));
316
- ElMessage.success("消息已复制");
322
+ ElMessage.success(t("system.ai.chat.message.messageCopied"));
317
323
  } catch {
318
- ElMessage.error("当前浏览器不支持复制");
324
+ ElMessage.error(t("system.ai.chat.message.copyUnsupported"));
319
325
  }
320
326
  }
321
327
 
@@ -332,7 +338,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
332
338
  if (item.role === "user") return !message.localOnly;
333
339
  return resolveMessageBubbleKey(message) !== messageKey;
334
340
  });
335
- ElMessage.success("消息已删除");
341
+ ElMessage.success(t("system.ai.chat.message.messageDeleted"));
336
342
  return;
337
343
  }
338
344
  await defAiMessageService.DeleteAiMessage({
@@ -340,7 +346,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
340
346
  message_id: String(item.id)
341
347
  });
342
348
  messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => String(message.id) !== String(item.id));
343
- ElMessage.success("消息已删除");
349
+ ElMessage.success(t("system.ai.chat.message.messageDeleted"));
344
350
  }
345
351
 
346
352
  /** 重试失败的一轮消息,或重新生成助手输出。 */
@@ -353,19 +359,19 @@ async function handleRetryMessage(item: ChatMessageItem) {
353
359
  if (item.localOnly) {
354
360
  const payload = resolveLocalRetryPayload(item);
355
361
  if (!payload) {
356
- ElMessage.warning("未找到可重新发送的本地消息");
362
+ ElMessage.warning(t("system.ai.chat.message.localRetryMissing"));
357
363
  return;
358
364
  }
359
365
  messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => !message.localOnly);
360
366
  if (await sendAiPayload(payload)) {
361
- ElMessage.success("已重新发送");
367
+ ElMessage.success(t("system.ai.chat.message.resent"));
362
368
  }
363
369
  return;
364
370
  }
365
371
  setSessionSending(sessionID, true);
366
372
  if (item.role === "user") {
367
373
  if (item.status !== AiMessageStatus.FAILED_AMS) {
368
- ElMessage.warning("只有发送失败的消息可以重新发送");
374
+ ElMessage.warning(t("system.ai.chat.message.retryFailedOnly"));
369
375
  return;
370
376
  }
371
377
  response = await defAiMessageService.RetryAiUserMessage({
@@ -382,10 +388,10 @@ async function handleRetryMessage(item: ChatMessageItem) {
382
388
  const current = messages.value[sessionID] ?? [];
383
389
  messages.value[sessionID] = replacePendingMessages(current, normalizeMessageList(response.messages));
384
390
  if (response.session) upsertSession(normalizeSession(response.session));
385
- ElMessage.success(item.role === "user" ? "已重新发送" : "已重新生成");
391
+ ElMessage.success(item.role === "user" ? t("system.ai.chat.message.resent") : t("system.ai.chat.message.regenerated"));
386
392
  } catch (error) {
387
393
  if (item.role !== "user") await loadMessages(sessionID, { force: true });
388
- const message = error instanceof Error ? error.message : "重新生成失败";
394
+ const message = error instanceof Error ? error.message : t("system.ai.chat.message.regenerateFailed");
389
395
  ElMessage.error(message);
390
396
  } finally {
391
397
  if (!item.localOnly) {
@@ -433,14 +439,14 @@ async function handleBranchMessage(item: ChatMessageItem) {
433
439
  upsertSession(branchSession);
434
440
  messages.value[branchSession.id] = normalizeMessageList(response.messages);
435
441
  activeSessionID.value = branchSession.id;
436
- ElMessage.success("已创建分支会话");
442
+ ElMessage.success(t("system.ai.chat.message.branchCreated"));
437
443
  }
438
444
 
439
445
  /** 朗读或停止朗读当前助手输出。 */
440
446
  function handleSpeakMessage(item: ChatMessageItem) {
441
447
  if (item.role === "user") return;
442
448
  if (!window.speechSynthesis) {
443
- ElMessage.warning("当前浏览器不支持朗读");
449
+ ElMessage.warning(t("system.ai.chat.message.speechUnsupported"));
444
450
  return;
445
451
  }
446
452
  const messageKey = resolveMessageBubbleKey(item);
@@ -450,7 +456,7 @@ function handleSpeakMessage(item: ChatMessageItem) {
450
456
  }
451
457
  stopSpeaking();
452
458
  const utterance = new SpeechSynthesisUtterance(String(item.content ?? ""));
453
- utterance.lang = "zh-CN";
459
+ utterance.lang = getCurrentLocale();
454
460
  utterance.onend = () => clearSpeakingState(messageKey);
455
461
  utterance.onerror = () => clearSpeakingState(messageKey);
456
462
  speakingMessageID = messageKey;
@@ -665,26 +671,34 @@ async function loadMessages(sessionID: string, options?: { force?: boolean }) {
665
671
 
666
672
  /** 重命名当前会话。 */
667
673
  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
- });
674
+ const { value } = await ElMessageBox.prompt(
675
+ t("system.ai.chat.dialog.renameDescription", { title: item.title }),
676
+ t("system.ai.chat.dialog.renameTitle"),
677
+ {
678
+ confirmButtonText: t("common.action.confirm"),
679
+ cancelButtonText: t("common.action.cancel"),
680
+ inputValue: item.title,
681
+ inputPattern: /\S+/,
682
+ inputErrorMessage: t("system.ai.chat.placeholder.conversationName")
683
+ }
684
+ );
675
685
 
676
686
  const response = await defAiSessionService.UpdateAiSession({ id: item.id, title: value.trim() });
677
687
  upsertSession(normalizeSession(response.session));
678
- ElMessage.success("会话已重命名");
688
+ ElMessage.success(t("system.ai.chat.message.conversationRenamed"));
679
689
  }
680
690
 
681
691
  /** 删除当前会话,并自动切换到剩余会话。 */
682
692
  async function handleDeleteSession(item: AiSession) {
683
- await ElMessageBox.confirm(`是否删除该会话?\n会话名称:${item.title}`, "删除会话", {
684
- confirmButtonText: "确认删除",
685
- cancelButtonText: "取消",
686
- type: "warning"
687
- });
693
+ await ElMessageBox.confirm(
694
+ t("system.ai.chat.dialog.deleteDescription", { title: item.title }),
695
+ t("system.ai.chat.dialog.deleteTitle"),
696
+ {
697
+ confirmButtonText: t("system.ai.chat.action.confirmDeleteConversation"),
698
+ cancelButtonText: t("common.action.cancel"),
699
+ type: "warning"
700
+ }
701
+ );
688
702
 
689
703
  await defAiSessionService.DeleteAiSession({ id: item.id });
690
704
  cancelSessionStreamTask(item.id);
@@ -697,7 +711,7 @@ async function handleDeleteSession(item: AiSession) {
697
711
  const nextSessionID = await ensureActiveSession();
698
712
  if (nextSessionID) await loadMessages(nextSessionID);
699
713
 
700
- ElMessage.success("会话已删除");
714
+ ElMessage.success(t("system.ai.chat.message.conversationDeleted"));
701
715
  }
702
716
 
703
717
  /** 保证当前存在可用会话;当列表为空时自动创建首个会话。 */
@@ -714,7 +728,7 @@ async function ensureActiveSession() {
714
728
  /** 创建新的助手会话,并同步到本地列表。 */
715
729
  async function createSession(options?: { title?: string }) {
716
730
  const response = await defAiSessionService.CreateAiSession({
717
- title: options?.title || "新对话",
731
+ title: options?.title || t("system.ai.chat.value.newConversation"),
718
732
  terminal: Terminal.TERMINAL_ADMIN
719
733
  });
720
734
  const normalizedSession = normalizeSession(response.session);
@@ -724,10 +738,12 @@ async function createSession(options?: { title?: string }) {
724
738
 
725
739
  /** 使用当前消息内容生成一个易识别的分支会话标题。 */
726
740
  function buildBranchSessionTitle(item: ChatMessageItem) {
727
- const content = String(item.input_content?.content || item.content || "新对话")
741
+ const content = String(item.input_content?.content || item.content || t("system.ai.chat.value.newConversation"))
728
742
  .replace(/\s+/g, " ")
729
743
  .trim();
730
- return `分支:${content.slice(0, 18) || "新对话"}`;
744
+ return t("system.ai.chat.value.branchTitle", {
745
+ title: content.slice(0, 18) || t("system.ai.chat.value.newConversation")
746
+ });
731
747
  }
732
748
 
733
749
  /** 归一化快捷入口,保证空态展示稳定排序。 */
@@ -8,12 +8,13 @@ import {
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
10
  import { AiMessageStatus, Terminal } from "@liujitcn/kratos-admin-system/rpc/base/v1/enum";
11
+ import { t } from "@liujitcn/kratos-admin-core";
11
12
  import type { AiStreamPayload, AIFlowBlock, ChatMessageItem, ReplySourceTag } from "./types";
12
13
 
13
14
  const THINKING_MESSAGE_ID_PREFIX = "ai-thinking";
14
15
  const LOCAL_USER_MESSAGE_ID_PREFIX = "ai-user-local";
15
16
  const PENDING_STREAM_MESSAGE_ID = "pending";
16
- const THINKING_MESSAGE_CONTENT = "正在整理回复";
17
+ const thinkingMessageContent = () => t("system.ai.chat.message.thinking");
17
18
 
18
19
  /** 生成流式消息分组键,确保同一轮回复只更新当前占位气泡。 */
19
20
  export function buildStreamMessageKey(sessionID: string, messageID: string) {
@@ -42,7 +43,7 @@ export function resolveTimestamp(timestamp?: { seconds?: number; nanos?: number
42
43
  export function normalizeSession(session?: Partial<AiSession> | null): AiSession {
43
44
  return {
44
45
  id: String(session?.id ?? ""),
45
- title: String(session?.title ?? "新对话"),
46
+ title: String(session?.title ?? t("system.ai.chat.value.newConversation")),
46
47
  summary: String(session?.summary ?? ""),
47
48
  updated_at: session?.updated_at,
48
49
  terminal: Number(session?.terminal ?? Terminal.TERMINAL_ADMIN)
@@ -60,16 +61,16 @@ export function resolveReplySourceTag(
60
61
  item: Pick<ChatMessageItem, "role" | "fallback" | "reply_source" | "model">
61
62
  ): ReplySourceTag | undefined {
62
63
  if (item.role === "user") return undefined;
63
- if (item.fallback) return { text: "降级回复", tone: "warning" };
64
+ if (item.fallback) return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
64
65
  switch (String(item.reply_source ?? "")) {
65
66
  case "network":
66
- return { text: "网络数据", tone: "success" };
67
+ return { text: t("system.ai.chat.source.network"), tone: "success" };
67
68
  case "llm":
68
- return { text: "模型回答", tone: "primary" };
69
+ return { text: t("system.ai.chat.source.model"), tone: "primary" };
69
70
  case "fallback":
70
- return { text: "降级回复", tone: "warning" };
71
+ return { text: t("system.ai.chat.source.fallback"), tone: "warning" };
71
72
  default:
72
- return item.model ? { text: "模型回答", tone: "primary" } : undefined;
73
+ return item.model ? { text: t("system.ai.chat.source.model"), tone: "primary" } : undefined;
73
74
  }
74
75
  }
75
76
 
@@ -236,7 +237,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
236
237
  input_content: undefined,
237
238
  output_content: {
238
239
  kind: "text",
239
- content: THINKING_MESSAGE_CONTENT,
240
+ content: thinkingMessageContent(),
240
241
  reply_source: "",
241
242
  model: "",
242
243
  fallback: false,
@@ -261,7 +262,7 @@ export function createThinkingMessage(options?: { sessionID?: string; messageID?
261
262
  message.progressState = "streaming";
262
263
  message.localOnly = true;
263
264
  message.streamKey = streamKey;
264
- message.replySourceTag = { text: "思考中", tone: "info" };
265
+ message.replySourceTag = { text: t("system.ai.chat.status.thinking"), tone: "info" };
265
266
  return message;
266
267
  }
267
268
 
@@ -290,7 +291,7 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
290
291
  if (String(item.id) !== messageID || item.role === "user") return item;
291
292
  return {
292
293
  ...item,
293
- content: THINKING_MESSAGE_CONTENT,
294
+ content: thinkingMessageContent(),
294
295
  fallback: false,
295
296
  fallback_reason: "",
296
297
  token: normalizeToken(),
@@ -298,7 +299,7 @@ export function markAIMessageRegenerating(current: ChatMessageItem[], sessionID:
298
299
  first_token_ms: 0,
299
300
  duration_ms: 0,
300
301
  progressState: "streaming",
301
- replySourceTag: { text: "思考中", tone: "info" },
302
+ replySourceTag: { text: t("system.ai.chat.status.thinking"), tone: "info" },
302
303
  status: AiMessageStatus.GENERATING_AMS,
303
304
  streamKey
304
305
  };
@@ -362,8 +363,8 @@ export function markThinkingMessageFailed(current: ChatMessageItem[], options?:
362
363
  ...item,
363
364
  progressState: "failed",
364
365
  status: AiMessageStatus.FAILED_AMS,
365
- content: "这次回复没有成功返回,你可以直接重试刚才的问题。",
366
- replySourceTag: { text: "发送失败", tone: "warning" }
366
+ content: t("system.ai.chat.message.replyFailed"),
367
+ replySourceTag: { text: t("system.ai.chat.status.sendFailed"), tone: "warning" }
367
368
  };
368
369
  });
369
370
  }
@@ -379,13 +380,13 @@ export function appendStreamingDelta(current: ChatMessageItem[], payload: AiStre
379
380
  const streamKey = buildStreamMessageKey(String(payload.session_id ?? ""), String(payload.message_id ?? ""));
380
381
  return current.map<ChatMessageItem>(item => {
381
382
  if (item.streamKey !== streamKey || (!item.localOnly && item.role === "user")) return item;
382
- const baseContent = item.content === THINKING_MESSAGE_CONTENT ? "" : item.content;
383
+ const baseContent = item.content === thinkingMessageContent() ? "" : item.content;
383
384
  const nextContent = `${baseContent}${payload.delta ?? ""}`;
384
385
  return {
385
386
  ...item,
386
387
  content: nextContent || item.content,
387
388
  progressState: "streaming",
388
- replySourceTag: { text: "回答中", tone: "info" }
389
+ replySourceTag: { text: t("system.ai.chat.status.answering"), tone: "info" }
389
390
  };
390
391
  });
391
392
  }
@@ -401,8 +402,8 @@ export function markStreamingError(current: ChatMessageItem[], payload: AiStream
401
402
  ...item,
402
403
  progressState: "failed",
403
404
  status: AiMessageStatus.FAILED_AMS,
404
- content: "这次回复没有成功返回,你可以直接重试刚才的问题。",
405
- replySourceTag: { text: "发送失败", tone: "warning" }
405
+ content: t("system.ai.chat.message.replyFailed"),
406
+ replySourceTag: { text: t("system.ai.chat.status.sendFailed"), tone: "warning" }
406
407
  };
407
408
  });
408
409
  }