@liujitcn/kratos-admin-system 0.0.21 → 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.
- package/dist/package/declarations/src/api/system/base_language.d.ts +5 -4
- package/dist/package/declarations/src/api/system/base_translation.d.ts +7 -4
- package/dist/package/declarations/src/api/system/ops_monitoring.d.ts +19 -0
- package/dist/package/declarations/src/api/system/ops_monitoring_sse.d.ts +12 -0
- package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +9 -32
- package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +3 -6
- package/dist/package/declarations/src/components/dynamicTranslation.d.ts +11 -17
- package/dist/package/declarations/src/locales/generated.d.ts +6536 -0
- package/dist/package/declarations/src/rpc/base/v1/ai_session.d.ts +12 -2
- package/dist/package/declarations/src/rpc/base/v1/ai_tool.d.ts +9 -1
- package/dist/package/declarations/src/rpc/base/v1/config.d.ts +35 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +1 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +23 -7
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +7 -77
- package/dist/package/declarations/src/rpc/system/admin/v1/base_job.d.ts +9 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_language.d.ts +7 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +5 -40
- package/dist/package/declarations/src/rpc/system/admin/v1/base_migration.d.ts +6 -6
- package/dist/package/declarations/src/rpc/system/admin/v1/base_role.d.ts +13 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/base_translation.d.ts +54 -81
- package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +11 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +11 -11
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_table.d.ts +11 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/common.d.ts +13 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +222 -0
- package/dist/package/declarations/src/views/tool/ops-monitoring/index.vue.d.ts +3 -0
- package/dist/package/src/api/base/ai_message.ts +2 -2
- package/dist/package/src/api/system/base_language.ts +13 -15
- package/dist/package/src/api/system/base_translation.ts +17 -6
- package/dist/package/src/api/system/ops_monitoring.ts +88 -0
- package/dist/package/src/api/system/ops_monitoring_sse.ts +49 -0
- package/dist/package/src/components/DynamicTranslationCell.vue +199 -126
- package/dist/package/src/components/DynamicTranslationEditor.vue +109 -78
- package/dist/package/src/components/dynamicTranslation.ts +11 -31
- package/dist/package/src/locales/README.md +7 -5
- package/dist/package/src/locales/en-US.json +876 -872
- package/dist/package/src/locales/es-ES.json +900 -895
- package/dist/package/src/locales/fr-FR.json +896 -891
- package/dist/package/src/locales/generated.ts +22 -0
- package/dist/package/src/locales/ja-JP.json +876 -872
- package/dist/package/src/locales/ko-KR.json +881 -876
- package/dist/package/src/locales/zh-CN.json +876 -872
- package/dist/package/src/locales/zh-TW.json +876 -871
- package/dist/package/src/module.ts +3 -17
- package/dist/package/src/rpc/base/v1/ai_session.ts +13 -2
- package/dist/package/src/rpc/base/v1/ai_tool.ts +10 -1
- package/dist/package/src/rpc/base/v1/config.ts +47 -0
- package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
- package/dist/package/src/rpc/system/admin/v1/base_config.ts +24 -7
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +7 -79
- package/dist/package/src/rpc/system/admin/v1/base_job.ts +10 -1
- package/dist/package/src/rpc/system/admin/v1/base_language.ts +8 -2
- package/dist/package/src/rpc/system/admin/v1/base_menu.ts +5 -41
- package/dist/package/src/rpc/system/admin/v1/base_migration.ts +8 -8
- package/dist/package/src/rpc/system/admin/v1/base_role.ts +14 -1
- package/dist/package/src/rpc/system/admin/v1/base_translation.ts +54 -81
- package/dist/package/src/rpc/system/admin/v1/base_user.ts +12 -1
- package/dist/package/src/rpc/system/admin/v1/code_gen.ts +11 -11
- package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +12 -1
- package/dist/package/src/rpc/system/admin/v1/common.ts +21 -0
- package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +255 -0
- package/dist/package/src/views/ai/chat/components/ChatPanel.vue +36 -36
- package/dist/package/src/views/ai/chat/components/SessionPanel.vue +6 -6
- package/dist/package/src/views/ai/chat/components/XSender.vue +20 -20
- package/dist/package/src/views/ai/chat/index.vue +33 -32
- package/dist/package/src/views/ai/chat/message.ts +16 -15
- package/dist/package/src/views/base/api/index.vue +55 -56
- package/dist/package/src/views/base/area/index.vue +18 -19
- package/dist/package/src/views/base/config/index.vue +143 -133
- package/dist/package/src/views/base/dept/index.vue +42 -43
- package/dist/package/src/views/base/dict/index.vue +49 -45
- package/dist/package/src/views/base/dict/item.vue +54 -49
- package/dist/package/src/views/base/job/index.vue +51 -52
- package/dist/package/src/views/base/job/log.vue +18 -18
- package/dist/package/src/views/{tool → base}/language/index.vue +51 -47
- package/dist/package/src/views/base/log/index.vue +40 -40
- package/dist/package/src/views/base/menu/index.vue +220 -177
- package/dist/package/src/views/base/migration/index.vue +24 -24
- package/dist/package/src/views/base/post/index.vue +42 -43
- package/dist/package/src/views/base/role/index.vue +54 -55
- package/dist/package/src/views/base/tenant/index.vue +42 -43
- package/dist/package/src/views/base/user/components/dept-tree.vue +1 -1
- package/dist/package/src/views/base/user/index.vue +69 -71
- package/dist/package/src/views/profile/components/base.vue +9 -9
- package/dist/package/src/views/profile/components/password.vue +19 -20
- package/dist/package/src/views/profile/components/security.vue +20 -20
- package/dist/package/src/views/profile/index.vue +3 -3
- package/dist/package/src/views/tool/api-doc/index.vue +1 -1
- package/dist/package/src/views/tool/code-gen/code-preview/index.vue +13 -13
- package/dist/package/src/views/tool/code-gen/columns/index.vue +89 -89
- package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +5 -5
- package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +21 -21
- package/dist/package/src/views/tool/code-gen/components/CodePreviewPane.vue +5 -5
- package/dist/package/src/views/tool/code-gen/config.ts +60 -60
- package/dist/package/src/views/tool/code-gen/preview/data.ts +2 -2
- package/dist/package/src/views/tool/code-gen/preview/index.vue +30 -31
- package/dist/package/src/views/tool/code-gen/proto/index.vue +43 -43
- package/dist/package/src/views/tool/code-gen/table/index.vue +95 -95
- package/dist/package/src/views/tool/ops-monitoring/index.vue +1175 -0
- package/dist/package/src/views/tool/project-doc/index.vue +7 -7
- package/package.json +2 -2
- package/dist/package/declarations/src/rpc/base/v1/enum.d.ts +0 -43
- package/dist/package/declarations/src/rpc/system/common/v1/enum.d.ts +0 -67
- package/dist/package/src/rpc/base/v1/enum.ts +0 -54
- package/dist/package/src/rpc/system/common/v1/enum.ts +0 -80
- /package/dist/package/declarations/src/views/{tool → base}/language/index.vue.d.ts +0 -0
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
<template v-if="isEmptyState">
|
|
4
4
|
<div class="agent-chat-empty">
|
|
5
5
|
<div class="agent-chat-empty__title">{{ welcomeTitle }}</div>
|
|
6
|
-
<div class="agent-chat-empty__desc">{{ t("system.ai.chat.
|
|
6
|
+
<div class="agent-chat-empty__desc">{{ t("system.ai.chat.welcome_description") }}</div>
|
|
7
7
|
<section v-if="hasShortcutPanel" class="agent-shortcuts">
|
|
8
8
|
<div class="agent-shortcuts__head">
|
|
9
9
|
<div>
|
|
10
10
|
<div class="agent-shortcuts__eyebrow">{{ t("system.ai.chat.shortcut.eyebrow") }}</div>
|
|
11
|
-
<div class="agent-shortcuts__title">{{ t("system.ai.chat.shortcut.
|
|
11
|
+
<div class="agent-shortcuts__title">{{ t("system.ai.chat.shortcut.start_title") }}</div>
|
|
12
12
|
</div>
|
|
13
13
|
<div class="agent-shortcuts__actions">
|
|
14
14
|
<span class="agent-shortcuts__count">{{ shortcutBatchLabel }}</span>
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
:disabled="sending"
|
|
20
20
|
@click="refreshShortcutBatch"
|
|
21
21
|
>
|
|
22
|
-
<span>{{ t("system.ai.chat.action.
|
|
22
|
+
<span>{{ t("system.ai.chat.action.refresh_shortcuts") }}</span>
|
|
23
23
|
<el-icon><Refresh /></el-icon>
|
|
24
24
|
</button>
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
<div v-if="loadingShortcuts" class="agent-shortcuts__loading">
|
|
28
|
-
{{ t("system.ai.chat.message.
|
|
28
|
+
{{ t("system.ai.chat.message.loading_shortcuts") }}
|
|
29
29
|
</div>
|
|
30
30
|
<div v-else class="agent-shortcuts__grid">
|
|
31
31
|
<button
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
<button
|
|
107
107
|
class="agent-message-tool-copy"
|
|
108
108
|
type="button"
|
|
109
|
-
:aria-label="t('system.ai.chat.action.
|
|
109
|
+
:aria-label="t('system.ai.chat.action.copy_request')"
|
|
110
110
|
@click.stop="handleCopyToolRequest(tool)"
|
|
111
111
|
>
|
|
112
112
|
<el-icon><CopyDocument /></el-icon>
|
|
@@ -134,10 +134,10 @@
|
|
|
134
134
|
}"
|
|
135
135
|
>
|
|
136
136
|
<div v-if="isAIFailedMessage(item)" class="agent-message-error">
|
|
137
|
-
<div class="agent-message-error__title">{{ t("system.ai.chat.message.
|
|
137
|
+
<div class="agent-message-error__title">{{ t("system.ai.chat.message.server_error") }}</div>
|
|
138
138
|
<div class="agent-message-error__content">{{ resolveAIErrorMessage(item) }}</div>
|
|
139
139
|
<el-collapse v-if="item.fallback_reason" class="agent-message-error__detail" accordion>
|
|
140
|
-
<el-collapse-item :title="t('system.ai.chat.title.
|
|
140
|
+
<el-collapse-item :title="t('system.ai.chat.title.error_detail')" :name="String(item.id)">
|
|
141
141
|
<pre>{{ item.fallback_reason }}</pre>
|
|
142
142
|
</el-collapse-item>
|
|
143
143
|
</el-collapse>
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
<AiMarkdown :content="item.content" :streaming="item.progressState === 'streaming'" />
|
|
147
147
|
<slot name="flow-blocks" :message="item" :active-flow-message-id="activeFlowMessageID" />
|
|
148
148
|
<el-collapse v-if="item.fallback_reason" class="agent-message-error__detail" accordion>
|
|
149
|
-
<el-collapse-item :title="t('system.ai.chat.title.
|
|
149
|
+
<el-collapse-item :title="t('system.ai.chat.title.error_detail')" :name="String(item.id)">
|
|
150
150
|
<pre>{{ item.fallback_reason }}</pre>
|
|
151
151
|
</el-collapse-item>
|
|
152
152
|
</el-collapse>
|
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
<button
|
|
210
210
|
class="agent-message-action agent-message-runtime-trigger"
|
|
211
211
|
type="button"
|
|
212
|
-
:aria-label="t('system.ai.chat.action.
|
|
212
|
+
:aria-label="t('system.ai.chat.action.view_runtime')"
|
|
213
213
|
:disabled="item.progressState === 'streaming'"
|
|
214
214
|
>
|
|
215
215
|
<el-icon><DataAnalysis /></el-icon>
|
|
@@ -222,30 +222,30 @@
|
|
|
222
222
|
<div v-if="resolveTokenTotal(item) > 0" class="agent-runtime-detail__section">
|
|
223
223
|
<div class="agent-runtime-detail__section-title">Token</div>
|
|
224
224
|
<div class="agent-runtime-detail__row">
|
|
225
|
-
<span>{{ t("system.ai.chat.field.
|
|
225
|
+
<span>{{ t("system.ai.chat.field.input_tokens") }}</span>
|
|
226
226
|
<strong>{{ formatNumber(item.token?.input) }}</strong>
|
|
227
227
|
</div>
|
|
228
228
|
<div class="agent-runtime-detail__row">
|
|
229
|
-
<span>{{ t("system.ai.chat.field.
|
|
229
|
+
<span>{{ t("system.ai.chat.field.output_tokens") }}</span>
|
|
230
230
|
<strong>{{ formatNumber(item.token?.output) }}</strong>
|
|
231
231
|
</div>
|
|
232
232
|
<div v-if="(item.token?.cache ?? 0) > 0" class="agent-runtime-detail__row">
|
|
233
|
-
<span>{{ t("system.ai.chat.field.
|
|
233
|
+
<span>{{ t("system.ai.chat.field.cache_tokens") }}</span>
|
|
234
234
|
<strong>{{ formatNumber(item.token?.cache) }}</strong>
|
|
235
235
|
</div>
|
|
236
236
|
<div class="agent-runtime-detail__row is-total">
|
|
237
|
-
<span>{{ t("system.ai.chat.field.
|
|
237
|
+
<span>{{ t("system.ai.chat.field.total_tokens") }}</span>
|
|
238
238
|
<strong>{{ formatNumber(item.token?.total) }}</strong>
|
|
239
239
|
</div>
|
|
240
240
|
</div>
|
|
241
241
|
<div v-if="item.first_token_ms > 0 || item.duration_ms > 0" class="agent-runtime-detail__section">
|
|
242
242
|
<div class="agent-runtime-detail__section-title">{{ t("system.ai.chat.field.duration") }}</div>
|
|
243
243
|
<div v-if="item.first_token_ms > 0" class="agent-runtime-detail__row">
|
|
244
|
-
<span>{{ t("system.ai.chat.field.
|
|
244
|
+
<span>{{ t("system.ai.chat.field.first_token") }}</span>
|
|
245
245
|
<strong>{{ formatDurationMs(item.first_token_ms) }}</strong>
|
|
246
246
|
</div>
|
|
247
247
|
<div v-if="item.duration_ms > 0" class="agent-runtime-detail__row is-total">
|
|
248
|
-
<span>{{ t("system.ai.chat.field.
|
|
248
|
+
<span>{{ t("system.ai.chat.field.total_duration") }}</span>
|
|
249
249
|
<strong>{{ formatDurationMs(item.duration_ms) }}</strong>
|
|
250
250
|
</div>
|
|
251
251
|
</div>
|
|
@@ -282,7 +282,7 @@
|
|
|
282
282
|
<div class="agent-shortcuts__head">
|
|
283
283
|
<div>
|
|
284
284
|
<div class="agent-shortcuts__eyebrow">{{ t("system.ai.chat.shortcut.eyebrow") }}</div>
|
|
285
|
-
<div class="agent-shortcuts__title">{{ t("system.ai.chat.shortcut.
|
|
285
|
+
<div class="agent-shortcuts__title">{{ t("system.ai.chat.shortcut.continue_title") }}</div>
|
|
286
286
|
</div>
|
|
287
287
|
<div class="agent-shortcuts__actions">
|
|
288
288
|
<span class="agent-shortcuts__count">{{ shortcutBatchLabel }}</span>
|
|
@@ -293,13 +293,13 @@
|
|
|
293
293
|
:disabled="sending"
|
|
294
294
|
@click="refreshShortcutBatch"
|
|
295
295
|
>
|
|
296
|
-
<span>{{ t("system.ai.chat.action.
|
|
296
|
+
<span>{{ t("system.ai.chat.action.refresh_shortcuts") }}</span>
|
|
297
297
|
<el-icon><Refresh /></el-icon>
|
|
298
298
|
</button>
|
|
299
299
|
</div>
|
|
300
300
|
</div>
|
|
301
301
|
<div v-if="loadingShortcuts" class="agent-shortcuts__loading">
|
|
302
|
-
{{ t("system.ai.chat.message.
|
|
302
|
+
{{ t("system.ai.chat.message.loading_shortcuts") }}
|
|
303
303
|
</div>
|
|
304
304
|
<div v-else class="agent-shortcuts__grid">
|
|
305
305
|
<button
|
|
@@ -337,7 +337,7 @@ import { getCurrentLocale, t } from "@liujitcn/kratos-admin-core";
|
|
|
337
337
|
import type { AiAction } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_message";
|
|
338
338
|
import { type AiAttachment, type AiSession } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
339
339
|
import type { AiShortcut, AiToolCall } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
|
|
340
|
-
import { AiMessageStatus } from "@liujitcn/kratos-admin-system/rpc/base/v1/
|
|
340
|
+
import { AiMessageStatus } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
341
341
|
import XSender from "./XSender.vue";
|
|
342
342
|
|
|
343
343
|
// AI Markdown 渲染器依赖较重,仅在真正出现助手消息时再加载。
|
|
@@ -543,7 +543,7 @@ const canRefreshShortcutBatch = computed(() => shortcutAllList.value.length > SH
|
|
|
543
543
|
const shortcutBatchLabel = computed(() => {
|
|
544
544
|
const total = shortcutAllList.value.length;
|
|
545
545
|
if (props.loadingShortcuts && total === 0) return t("system.ai.chat.status.loading");
|
|
546
|
-
if (total <= SHORTCUT_BATCH_SIZE) return t("system.ai.chat.value.
|
|
546
|
+
if (total <= SHORTCUT_BATCH_SIZE) return t("system.ai.chat.value.item_count", { count: total });
|
|
547
547
|
const pageIndex = shortcutBatchIndex.value % shortcutBatchCount.value;
|
|
548
548
|
const start = pageIndex * SHORTCUT_BATCH_SIZE + 1;
|
|
549
549
|
const end = Math.min(start + SHORTCUT_BATCH_SIZE - 1, total);
|
|
@@ -638,9 +638,9 @@ function resolveShortcutIcon(shortcut: AiShortcut) {
|
|
|
638
638
|
|
|
639
639
|
/** 展示快捷入口的分组和工具依赖摘要,帮助运营判断动作上下文。 */
|
|
640
640
|
function resolveShortcutMeta(shortcut: AiShortcut) {
|
|
641
|
-
const group = shortcut.group || t("system.ai.chat.value.
|
|
641
|
+
const group = shortcut.group || t("system.ai.chat.value.general_assistant");
|
|
642
642
|
const toolCount = shortcut.required_tools?.length ?? 0;
|
|
643
|
-
return toolCount > 0 ? t("system.ai.chat.value.
|
|
643
|
+
return toolCount > 0 ? t("system.ai.chat.value.shortcut_tools", { group, count: toolCount }) : group;
|
|
644
644
|
}
|
|
645
645
|
|
|
646
646
|
/** 生成快捷入口对应的流程动作。 */
|
|
@@ -674,7 +674,7 @@ function parseActionPayload(payload?: string) {
|
|
|
674
674
|
|
|
675
675
|
/** 根据消息角色返回可用操作。 */
|
|
676
676
|
function resolveMessageActions(item: ChatMessageItem) {
|
|
677
|
-
if (item.progressState === "streaming" || item.status === AiMessageStatus.
|
|
677
|
+
if (item.progressState === "streaming" || item.status === AiMessageStatus.AI_MESSAGE_STATUS_GENERATING) return [];
|
|
678
678
|
|
|
679
679
|
const copyAction: MessageActionOption = {
|
|
680
680
|
key: "copy" as const,
|
|
@@ -685,7 +685,7 @@ function resolveMessageActions(item: ChatMessageItem) {
|
|
|
685
685
|
const editAction: MessageActionOption = { key: "edit" as const, label: t("common.action.edit"), icon: EditPen };
|
|
686
686
|
if (item.role === "user") {
|
|
687
687
|
const actions = isLastEditableUserMessage(item) ? [editAction, copyAction, deleteAction] : [copyAction, deleteAction];
|
|
688
|
-
if (item.status === AiMessageStatus.
|
|
688
|
+
if (item.status === AiMessageStatus.AI_MESSAGE_STATUS_FAILED) {
|
|
689
689
|
return item.localOnly
|
|
690
690
|
? [{ key: "retry" as const, label: t("system.ai.chat.action.resend"), icon: Refresh }, copyAction, deleteAction]
|
|
691
691
|
: [{ key: "retry" as const, label: t("system.ai.chat.action.resend"), icon: Refresh }, ...actions];
|
|
@@ -694,11 +694,11 @@ function resolveMessageActions(item: ChatMessageItem) {
|
|
|
694
694
|
}
|
|
695
695
|
|
|
696
696
|
const actions: MessageActionOption[] = [{ key: "retry" as const, label: t("system.ai.chat.action.regenerate"), icon: Refresh }];
|
|
697
|
-
if (item.status === AiMessageStatus.
|
|
698
|
-
actions.push({ key: "branch" as const, label: t("system.ai.chat.action.
|
|
697
|
+
if (item.status === AiMessageStatus.AI_MESSAGE_STATUS_SUCCESS) {
|
|
698
|
+
actions.push({ key: "branch" as const, label: t("system.ai.chat.action.create_branch"), icon: BranchActionIcon });
|
|
699
699
|
actions.push({
|
|
700
700
|
key: "speak" as const,
|
|
701
|
-
label: item.speaking ? t("system.ai.chat.action.
|
|
701
|
+
label: item.speaking ? t("system.ai.chat.action.stop_speaking") : t("system.ai.chat.action.speak"),
|
|
702
702
|
icon: SpeakActionIcon
|
|
703
703
|
});
|
|
704
704
|
}
|
|
@@ -707,13 +707,13 @@ function resolveMessageActions(item: ChatMessageItem) {
|
|
|
707
707
|
|
|
708
708
|
/** 判断是否为需要渲染错误卡片的助手失败消息。 */
|
|
709
709
|
function isAIFailedMessage(item: ChatMessageItem) {
|
|
710
|
-
return item.role !== "user" && item.status === AiMessageStatus.
|
|
710
|
+
return item.role !== "user" && item.status === AiMessageStatus.AI_MESSAGE_STATUS_FAILED;
|
|
711
711
|
}
|
|
712
712
|
|
|
713
713
|
/** 返回助手错误摘要,优先展示服务端可读错误。 */
|
|
714
714
|
function resolveAIErrorMessage(item: ChatMessageItem) {
|
|
715
715
|
const content = String(item.content ?? "").trim();
|
|
716
|
-
return content || t("system.ai.chat.message.
|
|
716
|
+
return content || t("system.ai.chat.message.reply_failed");
|
|
717
717
|
}
|
|
718
718
|
|
|
719
719
|
/** 判断助手消息是否存在最终用量信息。 */
|
|
@@ -893,9 +893,9 @@ function formatToolArgumentValue(value: unknown) {
|
|
|
893
893
|
async function handleCopyToolRequest(tool: AiToolCall) {
|
|
894
894
|
try {
|
|
895
895
|
await navigator.clipboard.writeText(formatToolRequest(tool));
|
|
896
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
896
|
+
ElMessage.success(t("system.ai.chat.message.request_copied"));
|
|
897
897
|
} catch {
|
|
898
|
-
ElMessage.error(t("system.ai.chat.message.
|
|
898
|
+
ElMessage.error(t("system.ai.chat.message.copy_unsupported"));
|
|
899
899
|
}
|
|
900
900
|
}
|
|
901
901
|
|
|
@@ -941,11 +941,11 @@ function submitMessageEdit(item: ChatMessageItem) {
|
|
|
941
941
|
if (props.sending) return;
|
|
942
942
|
const content = editingContent.value;
|
|
943
943
|
if (content === "") {
|
|
944
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
944
|
+
ElMessage.warning(t("system.ai.chat.message.content_required"));
|
|
945
945
|
return;
|
|
946
946
|
}
|
|
947
947
|
if (content === String(item.content ?? "")) {
|
|
948
|
-
ElMessage.info(t("system.ai.chat.message.
|
|
948
|
+
ElMessage.info(t("system.ai.chat.message.content_unchanged"));
|
|
949
949
|
return;
|
|
950
950
|
}
|
|
951
951
|
emit("messageEdit", { item, content });
|
|
@@ -959,9 +959,9 @@ function shouldConfirmMessageAction(action: ChatMessageAction) {
|
|
|
959
959
|
|
|
960
960
|
/** 返回消息操作确认文案,避免误删或误覆盖当前气泡。 */
|
|
961
961
|
function resolveActionConfirmTitle(action: ChatMessageAction, item: ChatMessageItem) {
|
|
962
|
-
if (action === "delete") return t("system.ai.chat.dialog.
|
|
963
|
-
if (item.role === "user") return t("system.ai.chat.dialog.
|
|
964
|
-
return t("system.ai.chat.dialog.
|
|
962
|
+
if (action === "delete") return t("system.ai.chat.dialog.confirm_delete_message");
|
|
963
|
+
if (item.role === "user") return t("system.ai.chat.dialog.confirm_resend_message");
|
|
964
|
+
return t("system.ai.chat.dialog.confirm_regenerate_message");
|
|
965
965
|
}
|
|
966
966
|
|
|
967
967
|
/** 统一回复来源标签配色。 */
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
<aside class="agent-session-panel">
|
|
3
3
|
<el-input
|
|
4
4
|
:model-value="keyword"
|
|
5
|
-
:placeholder="t('system.ai.chat.placeholder.
|
|
5
|
+
:placeholder="t('system.ai.chat.placeholder.search_conversation')"
|
|
6
6
|
clearable
|
|
7
7
|
:prefix-icon="Search"
|
|
8
8
|
@update:model-value="handleKeywordUpdate"
|
|
9
9
|
/>
|
|
10
10
|
<div class="agent-divider"></div>
|
|
11
11
|
<div class="agent-panel-header">
|
|
12
|
-
<div class="agent-panel-title">{{ t("system.ai.chat.title.
|
|
12
|
+
<div class="agent-panel-title">{{ t("system.ai.chat.title.recent_conversations") }}</div>
|
|
13
13
|
<div class="agent-panel-actions">
|
|
14
|
-
<el-tooltip :content="t('system.ai.chat.action.
|
|
14
|
+
<el-tooltip :content="t('system.ai.chat.action.collapse_sessions')" placement="top">
|
|
15
15
|
<button
|
|
16
16
|
class="agent-panel-icon"
|
|
17
17
|
type="button"
|
|
18
|
-
:aria-label="t('system.ai.chat.action.
|
|
18
|
+
:aria-label="t('system.ai.chat.action.collapse_sessions')"
|
|
19
19
|
@click="$emit('toggleCollapse')"
|
|
20
20
|
>
|
|
21
21
|
<el-icon><DArrowLeft /></el-icon>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
<button
|
|
25
25
|
class="agent-panel-create"
|
|
26
26
|
type="button"
|
|
27
|
-
:aria-label="t('system.ai.chat.action.
|
|
27
|
+
:aria-label="t('system.ai.chat.action.new_conversation')"
|
|
28
28
|
@click="handleCreateSession"
|
|
29
29
|
>
|
|
30
30
|
<el-icon><Plus /></el-icon>
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
@click.stop
|
|
59
59
|
@command="command => handleMenuCommand(command, item)"
|
|
60
60
|
>
|
|
61
|
-
<button class="agent-session-more" type="button" :aria-label="t('system.ai.chat.action.
|
|
61
|
+
<button class="agent-session-more" type="button" :aria-label="t('system.ai.chat.action.conversation_menu')">
|
|
62
62
|
<el-icon><MoreFilled /></el-icon>
|
|
63
63
|
</button>
|
|
64
64
|
<template #dropdown>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
class="agent-icon-button"
|
|
32
32
|
type="button"
|
|
33
33
|
:disabled="sending || uploading"
|
|
34
|
-
:aria-label="t('system.ai.chat.action.
|
|
34
|
+
:aria-label="t('system.ai.chat.action.upload_attachment')"
|
|
35
35
|
>
|
|
36
36
|
<el-icon :class="{ 'is-loading': uploading }">
|
|
37
37
|
<Loading v-if="uploading" />
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
</button>
|
|
41
41
|
</template>
|
|
42
42
|
<div class="agent-popover-card">
|
|
43
|
-
<div class="agent-popover-title">{{ t("system.ai.chat.action.
|
|
44
|
-
<div class="agent-popover-desc">{{ t("system.ai.chat.message.
|
|
43
|
+
<div class="agent-popover-title">{{ t("system.ai.chat.action.upload_attachment") }}</div>
|
|
44
|
+
<div class="agent-popover-desc">{{ t("system.ai.chat.message.attachment_hint") }}</div>
|
|
45
45
|
<button class="agent-popover-action" type="button" :disabled="sending || uploading" @click="handleSelectAttachment">
|
|
46
|
-
{{ uploading ? t("system.ai.chat.status.uploading") : t("system.ai.chat.action.
|
|
46
|
+
{{ uploading ? t("system.ai.chat.status.uploading") : t("system.ai.chat.action.select_local_file") }}
|
|
47
47
|
</button>
|
|
48
48
|
</div>
|
|
49
49
|
</el-popover>
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
<template #action-list>
|
|
56
56
|
<div class="agent-sender-actions">
|
|
57
57
|
<el-tooltip
|
|
58
|
-
:content="recording ? t('system.ai.chat.action.
|
|
58
|
+
:content="recording ? t('system.ai.chat.action.stop_voice_input') : t('system.ai.chat.action.voice_input')"
|
|
59
59
|
placement="top"
|
|
60
60
|
>
|
|
61
61
|
<button
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
type="button"
|
|
65
65
|
:disabled="sending"
|
|
66
66
|
:aria-pressed="recording"
|
|
67
|
-
:aria-label="recording ? t('system.ai.chat.action.
|
|
67
|
+
:aria-label="recording ? t('system.ai.chat.action.stop_voice_input') : t('system.ai.chat.action.voice_input')"
|
|
68
68
|
@click="handleToggleRecord"
|
|
69
69
|
>
|
|
70
70
|
<el-icon :class="{ 'is-loading': recording }">
|
|
@@ -164,12 +164,12 @@ const {
|
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
const actionHintText = computed(() => {
|
|
167
|
-
if (recording.value) return t("system.ai.chat.status.
|
|
168
|
-
if (uploading.value) return t("system.ai.chat.status.
|
|
167
|
+
if (recording.value) return t("system.ai.chat.status.recognizing_voice");
|
|
168
|
+
if (uploading.value) return t("system.ai.chat.status.uploading_attachments");
|
|
169
169
|
if (selectedAttachments.value.length) {
|
|
170
|
-
return t("system.ai.chat.value.
|
|
170
|
+
return t("system.ai.chat.value.selected_attachments", { count: selectedAttachments.value.length });
|
|
171
171
|
}
|
|
172
|
-
return t("system.ai.chat.value.
|
|
172
|
+
return t("system.ai.chat.value.attachments_available");
|
|
173
173
|
});
|
|
174
174
|
|
|
175
175
|
const attachmentItems = computed<FilesCardProps[]>(() =>
|
|
@@ -196,7 +196,7 @@ function handleSubmit() {
|
|
|
196
196
|
if (!trimmedText && selectedAttachments.value.length === 0) return;
|
|
197
197
|
|
|
198
198
|
emit("submit", {
|
|
199
|
-
text: trimmedText || t("system.ai.chat.value.
|
|
199
|
+
text: trimmedText || t("system.ai.chat.value.analyze_attachments"),
|
|
200
200
|
attachments: [...selectedAttachments.value]
|
|
201
201
|
});
|
|
202
202
|
inputText.value = "";
|
|
@@ -275,12 +275,12 @@ function matchCumulativeRecordCandidate(text: string, candidate: string) {
|
|
|
275
275
|
|
|
276
276
|
/** 根据浏览器语音识别错误类型生成用户可理解的提示。 */
|
|
277
277
|
function resolveRecordErrorMessage(error: RecordError) {
|
|
278
|
-
if (error.code === -1) return t("system.ai.chat.message.
|
|
278
|
+
if (error.code === -1) return t("system.ai.chat.message.voice_unsupported");
|
|
279
279
|
const errorName = error.error ?? "";
|
|
280
280
|
if (["not-allowed", "service-not-allowed", "permission-denied"].includes(errorName)) {
|
|
281
|
-
return t("system.ai.chat.message.
|
|
281
|
+
return t("system.ai.chat.message.microphone_denied");
|
|
282
282
|
}
|
|
283
|
-
return t("system.ai.chat.message.
|
|
283
|
+
return t("system.ai.chat.message.voice_failed");
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
/** 同步输入器内部文本,保证发送按钮禁用态能实时响应。 */
|
|
@@ -327,10 +327,10 @@ async function uploadAttachments(files: File[]) {
|
|
|
327
327
|
});
|
|
328
328
|
selectedAttachments.value = Array.from(attachmentMap.values());
|
|
329
329
|
if (response?.files?.length) {
|
|
330
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
330
|
+
ElMessage.success(t("system.ai.chat.message.attachments_uploaded", { count: response.files.length }));
|
|
331
331
|
}
|
|
332
332
|
} catch {
|
|
333
|
-
ElMessage.error(t("system.ai.chat.message.
|
|
333
|
+
ElMessage.error(t("system.ai.chat.message.attachment_upload_failed"));
|
|
334
334
|
} finally {
|
|
335
335
|
uploading.value = false;
|
|
336
336
|
resetFileInput();
|
|
@@ -341,22 +341,22 @@ async function uploadAttachments(files: File[]) {
|
|
|
341
341
|
function filterUploadFiles(files: File[]) {
|
|
342
342
|
const remainingCount = maxAttachmentCount - selectedAttachments.value.length;
|
|
343
343
|
if (remainingCount <= 0) {
|
|
344
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
344
|
+
ElMessage.warning(t("system.ai.chat.message.attachment_limit", { count: maxAttachmentCount }));
|
|
345
345
|
return [];
|
|
346
346
|
}
|
|
347
347
|
const validFiles = files.filter(file => {
|
|
348
348
|
if (!isAcceptedAttachmentFile(file)) {
|
|
349
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
349
|
+
ElMessage.warning(t("system.ai.chat.message.attachment_unsupported", { name: file.name }));
|
|
350
350
|
return false;
|
|
351
351
|
}
|
|
352
352
|
if (file.size > maxAttachmentSize) {
|
|
353
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
353
|
+
ElMessage.warning(t("system.ai.chat.message.attachment_too_large", { name: file.name, size: maxAttachmentSizeMB }));
|
|
354
354
|
return false;
|
|
355
355
|
}
|
|
356
356
|
return true;
|
|
357
357
|
});
|
|
358
358
|
if (validFiles.length > remainingCount) {
|
|
359
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
359
|
+
ElMessage.warning(t("system.ai.chat.message.attachment_remaining", { count: remainingCount }));
|
|
360
360
|
}
|
|
361
361
|
return validFiles.slice(0, remainingCount);
|
|
362
362
|
}
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
<button
|
|
15
15
|
class="agent-session-collapsed__toggle"
|
|
16
16
|
type="button"
|
|
17
|
-
:aria-label="t('system.ai.chat.action.
|
|
17
|
+
:aria-label="t('system.ai.chat.action.expand_sessions')"
|
|
18
18
|
@click="toggleSessionPanel"
|
|
19
19
|
>
|
|
20
20
|
<el-icon><DArrowRight /></el-icon>
|
|
21
21
|
</button>
|
|
22
|
-
<span class="agent-session-collapsed__label">{{ t("system.ai.chat.title.
|
|
22
|
+
<span class="agent-session-collapsed__label">{{ t("system.ai.chat.title.recent_conversations") }}</span>
|
|
23
23
|
</div>
|
|
24
24
|
<ChatPanel
|
|
25
25
|
:active-session="activeSession"
|
|
@@ -57,7 +57,8 @@ import { defAiToolService } from "@liujitcn/kratos-admin-system/api/base/ai_tool
|
|
|
57
57
|
import type { AiAction } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_message";
|
|
58
58
|
import type { AiSession } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_session";
|
|
59
59
|
import type { AiShortcut } from "@liujitcn/kratos-admin-system/rpc/base/v1/ai_tool";
|
|
60
|
-
import { AiMessageStatus
|
|
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";
|
|
61
62
|
import ChatPanel from "./components/ChatPanel.vue";
|
|
62
63
|
import SessionPanel from "./components/SessionPanel.vue";
|
|
63
64
|
import {
|
|
@@ -151,7 +152,7 @@ async function handleSessionAction(payload: { action: SessionAction; item: AiSes
|
|
|
151
152
|
await handleDeleteSession(payload.item);
|
|
152
153
|
} catch (error) {
|
|
153
154
|
if (error === "cancel" || error === "close") {
|
|
154
|
-
ElMessage.info(t("system.ai.chat.message.
|
|
155
|
+
ElMessage.info(t("system.ai.chat.message.action_canceled"));
|
|
155
156
|
}
|
|
156
157
|
}
|
|
157
158
|
}
|
|
@@ -162,7 +163,7 @@ async function handleCreateSession() {
|
|
|
162
163
|
if (!sessionID) return;
|
|
163
164
|
activeSessionID.value = sessionID;
|
|
164
165
|
messages.value[sessionID] = [];
|
|
165
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
166
|
+
ElMessage.success(t("system.ai.chat.message.conversation_created"));
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
/** 提交用户输入并同步消息流。 */
|
|
@@ -226,7 +227,7 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
|
|
|
226
227
|
);
|
|
227
228
|
|
|
228
229
|
if (!response.body) {
|
|
229
|
-
throw new Error(t("system.ai.chat.message.
|
|
230
|
+
throw new Error(t("system.ai.chat.message.empty_stream"));
|
|
230
231
|
}
|
|
231
232
|
await readAiEventStream(
|
|
232
233
|
response.body,
|
|
@@ -236,14 +237,14 @@ async function runAiStreamTask(sessionID: string, payload: SubmitPayload) {
|
|
|
236
237
|
controller.signal
|
|
237
238
|
);
|
|
238
239
|
if (!task.finished && !controller.signal.aborted) {
|
|
239
|
-
throw new Error(t("system.ai.chat.message.
|
|
240
|
+
throw new Error(t("system.ai.chat.message.incomplete_stream"));
|
|
240
241
|
}
|
|
241
242
|
} catch (error) {
|
|
242
243
|
if (controller.signal.aborted) return;
|
|
243
244
|
messages.value[sessionID] = markThinkingMessageFailed(messages.value[sessionID] ?? [], {
|
|
244
245
|
sessionID
|
|
245
246
|
});
|
|
246
|
-
const message = error instanceof Error ? error.message : t("system.ai.chat.message.
|
|
247
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.request_failed");
|
|
247
248
|
ElMessage.error(message);
|
|
248
249
|
} finally {
|
|
249
250
|
if (runningStreamTaskMap.get(sessionID) === task) {
|
|
@@ -305,10 +306,10 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
|
|
|
305
306
|
const currentMessages = messages.value[sessionID] ?? [];
|
|
306
307
|
messages.value[sessionID] = replacePendingMessages(currentMessages, normalizeMessageList(response.messages));
|
|
307
308
|
if (response.session) upsertSession(normalizeSession(response.session));
|
|
308
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
309
|
+
ElMessage.success(t("system.ai.chat.message.updated_and_regenerated"));
|
|
309
310
|
} catch (error) {
|
|
310
311
|
await loadMessages(sessionID, { force: true });
|
|
311
|
-
const message = error instanceof Error ? error.message : t("system.ai.chat.message.
|
|
312
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.update_failed");
|
|
312
313
|
ElMessage.error(message);
|
|
313
314
|
} finally {
|
|
314
315
|
setSessionSending(sessionID, false);
|
|
@@ -319,9 +320,9 @@ async function handleEditMessage(payload: ChatMessageEditPayload) {
|
|
|
319
320
|
async function handleCopyMessage(item: ChatMessageItem) {
|
|
320
321
|
try {
|
|
321
322
|
await navigator.clipboard.writeText(String(item.content ?? ""));
|
|
322
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
323
|
+
ElMessage.success(t("system.ai.chat.message.message_copied"));
|
|
323
324
|
} catch {
|
|
324
|
-
ElMessage.error(t("system.ai.chat.message.
|
|
325
|
+
ElMessage.error(t("system.ai.chat.message.copy_unsupported"));
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
328
|
|
|
@@ -338,7 +339,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
|
|
|
338
339
|
if (item.role === "user") return !message.localOnly;
|
|
339
340
|
return resolveMessageBubbleKey(message) !== messageKey;
|
|
340
341
|
});
|
|
341
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
342
|
+
ElMessage.success(t("system.ai.chat.message.message_deleted"));
|
|
342
343
|
return;
|
|
343
344
|
}
|
|
344
345
|
await defAiMessageService.DeleteAiMessage({
|
|
@@ -346,7 +347,7 @@ async function handleDeleteMessage(item: ChatMessageItem) {
|
|
|
346
347
|
message_id: String(item.id)
|
|
347
348
|
});
|
|
348
349
|
messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => String(message.id) !== String(item.id));
|
|
349
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
350
|
+
ElMessage.success(t("system.ai.chat.message.message_deleted"));
|
|
350
351
|
}
|
|
351
352
|
|
|
352
353
|
/** 重试失败的一轮消息,或重新生成助手输出。 */
|
|
@@ -359,7 +360,7 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
359
360
|
if (item.localOnly) {
|
|
360
361
|
const payload = resolveLocalRetryPayload(item);
|
|
361
362
|
if (!payload) {
|
|
362
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
363
|
+
ElMessage.warning(t("system.ai.chat.message.local_retry_missing"));
|
|
363
364
|
return;
|
|
364
365
|
}
|
|
365
366
|
messages.value[sessionID] = (messages.value[sessionID] ?? []).filter(message => !message.localOnly);
|
|
@@ -370,8 +371,8 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
370
371
|
}
|
|
371
372
|
setSessionSending(sessionID, true);
|
|
372
373
|
if (item.role === "user") {
|
|
373
|
-
if (item.status !== AiMessageStatus.
|
|
374
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
374
|
+
if (item.status !== AiMessageStatus.AI_MESSAGE_STATUS_FAILED) {
|
|
375
|
+
ElMessage.warning(t("system.ai.chat.message.retry_failed_only"));
|
|
375
376
|
return;
|
|
376
377
|
}
|
|
377
378
|
response = await defAiMessageService.RetryAiUserMessage({
|
|
@@ -391,7 +392,7 @@ async function handleRetryMessage(item: ChatMessageItem) {
|
|
|
391
392
|
ElMessage.success(item.role === "user" ? t("system.ai.chat.message.resent") : t("system.ai.chat.message.regenerated"));
|
|
392
393
|
} catch (error) {
|
|
393
394
|
if (item.role !== "user") await loadMessages(sessionID, { force: true });
|
|
394
|
-
const message = error instanceof Error ? error.message : t("system.ai.chat.message.
|
|
395
|
+
const message = error instanceof Error ? error.message : t("system.ai.chat.message.regenerate_failed");
|
|
395
396
|
ElMessage.error(message);
|
|
396
397
|
} finally {
|
|
397
398
|
if (!item.localOnly) {
|
|
@@ -439,14 +440,14 @@ async function handleBranchMessage(item: ChatMessageItem) {
|
|
|
439
440
|
upsertSession(branchSession);
|
|
440
441
|
messages.value[branchSession.id] = normalizeMessageList(response.messages);
|
|
441
442
|
activeSessionID.value = branchSession.id;
|
|
442
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
443
|
+
ElMessage.success(t("system.ai.chat.message.branch_created"));
|
|
443
444
|
}
|
|
444
445
|
|
|
445
446
|
/** 朗读或停止朗读当前助手输出。 */
|
|
446
447
|
function handleSpeakMessage(item: ChatMessageItem) {
|
|
447
448
|
if (item.role === "user") return;
|
|
448
449
|
if (!window.speechSynthesis) {
|
|
449
|
-
ElMessage.warning(t("system.ai.chat.message.
|
|
450
|
+
ElMessage.warning(t("system.ai.chat.message.speech_unsupported"));
|
|
450
451
|
return;
|
|
451
452
|
}
|
|
452
453
|
const messageKey = resolveMessageBubbleKey(item);
|
|
@@ -672,29 +673,29 @@ async function loadMessages(sessionID: string, options?: { force?: boolean }) {
|
|
|
672
673
|
/** 重命名当前会话。 */
|
|
673
674
|
async function handleRenameSession(item: AiSession) {
|
|
674
675
|
const { value } = await ElMessageBox.prompt(
|
|
675
|
-
t("system.ai.chat.dialog.
|
|
676
|
-
t("system.ai.chat.dialog.
|
|
676
|
+
t("system.ai.chat.dialog.rename_description", { title: item.title }),
|
|
677
|
+
t("system.ai.chat.dialog.rename_title"),
|
|
677
678
|
{
|
|
678
679
|
confirmButtonText: t("common.action.confirm"),
|
|
679
680
|
cancelButtonText: t("common.action.cancel"),
|
|
680
681
|
inputValue: item.title,
|
|
681
682
|
inputPattern: /\S+/,
|
|
682
|
-
inputErrorMessage: t("system.ai.chat.placeholder.
|
|
683
|
+
inputErrorMessage: t("system.ai.chat.placeholder.conversation_name")
|
|
683
684
|
}
|
|
684
685
|
);
|
|
685
686
|
|
|
686
687
|
const response = await defAiSessionService.UpdateAiSession({ id: item.id, title: value.trim() });
|
|
687
688
|
upsertSession(normalizeSession(response.session));
|
|
688
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
689
|
+
ElMessage.success(t("system.ai.chat.message.conversation_renamed"));
|
|
689
690
|
}
|
|
690
691
|
|
|
691
692
|
/** 删除当前会话,并自动切换到剩余会话。 */
|
|
692
693
|
async function handleDeleteSession(item: AiSession) {
|
|
693
694
|
await ElMessageBox.confirm(
|
|
694
|
-
t("system.ai.chat.dialog.
|
|
695
|
-
t("system.ai.chat.dialog.
|
|
695
|
+
t("system.ai.chat.dialog.delete_description", { title: item.title }),
|
|
696
|
+
t("system.ai.chat.dialog.delete_title"),
|
|
696
697
|
{
|
|
697
|
-
confirmButtonText: t("system.ai.chat.action.
|
|
698
|
+
confirmButtonText: t("system.ai.chat.action.confirm_delete_conversation"),
|
|
698
699
|
cancelButtonText: t("common.action.cancel"),
|
|
699
700
|
type: "warning"
|
|
700
701
|
}
|
|
@@ -711,7 +712,7 @@ async function handleDeleteSession(item: AiSession) {
|
|
|
711
712
|
const nextSessionID = await ensureActiveSession();
|
|
712
713
|
if (nextSessionID) await loadMessages(nextSessionID);
|
|
713
714
|
|
|
714
|
-
ElMessage.success(t("system.ai.chat.message.
|
|
715
|
+
ElMessage.success(t("system.ai.chat.message.conversation_deleted"));
|
|
715
716
|
}
|
|
716
717
|
|
|
717
718
|
/** 保证当前存在可用会话;当列表为空时自动创建首个会话。 */
|
|
@@ -728,7 +729,7 @@ async function ensureActiveSession() {
|
|
|
728
729
|
/** 创建新的助手会话,并同步到本地列表。 */
|
|
729
730
|
async function createSession(options?: { title?: string }) {
|
|
730
731
|
const response = await defAiSessionService.CreateAiSession({
|
|
731
|
-
title: options?.title || t("system.ai.chat.value.
|
|
732
|
+
title: options?.title || t("system.ai.chat.value.new_conversation"),
|
|
732
733
|
terminal: Terminal.TERMINAL_ADMIN
|
|
733
734
|
});
|
|
734
735
|
const normalizedSession = normalizeSession(response.session);
|
|
@@ -738,11 +739,11 @@ async function createSession(options?: { title?: string }) {
|
|
|
738
739
|
|
|
739
740
|
/** 使用当前消息内容生成一个易识别的分支会话标题。 */
|
|
740
741
|
function buildBranchSessionTitle(item: ChatMessageItem) {
|
|
741
|
-
const content = String(item.input_content?.content || item.content || t("system.ai.chat.value.
|
|
742
|
+
const content = String(item.input_content?.content || item.content || t("system.ai.chat.value.new_conversation"))
|
|
742
743
|
.replace(/\s+/g, " ")
|
|
743
744
|
.trim();
|
|
744
|
-
return t("system.ai.chat.value.
|
|
745
|
-
title: content.slice(0, 18) || t("system.ai.chat.value.
|
|
745
|
+
return t("system.ai.chat.value.branch_title", {
|
|
746
|
+
title: content.slice(0, 18) || t("system.ai.chat.value.new_conversation")
|
|
746
747
|
});
|
|
747
748
|
}
|
|
748
749
|
|