From 11b579eb87910f22b75bff6ee1a769861bbcf671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Fri, 19 Jun 2026 12:25:10 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84:=20=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E5=AE=A1=E6=9F=A5=E9=99=8D=E6=8A=80=E6=9C=AF?= =?UTF-8?q?=E5=80=BA=C2=B7i18n=E6=94=B6=E5=8F=A3(=E9=AB=98ROI)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新建 src/i18n/i18n-helpers.ts: 类型安全 t + currentLocale(any中转内部1处带注释) - 12文件改 i18n as any 样板收口: utils/time + stores(knowledge/project/{ideas,projects,tasks,workflow}) + composables(aiShared/useAiConversations/useAiEvents/useAiSend/useAiStream/useToolCard) - as any 22→10(i18n 13→0对外), 签名统一(key, named?) - useToolCard文档块同步(防AI被过时注释误导) --- src/composables/ai/aiShared.ts | 4 +-- src/composables/ai/useAiConversations.ts | 5 +--- src/composables/ai/useAiEvents.ts | 7 +----- src/composables/ai/useAiSend.ts | 4 +-- src/composables/ai/useAiStream.ts | 6 +---- src/composables/ai/useToolCard.ts | 10 +++----- src/i18n/i18n-helpers.ts | 32 ++++++++++++++++++++++++ src/stores/knowledge.ts | 5 +--- src/stores/project/ideas.ts | 5 +--- src/stores/project/projects.ts | 5 +--- src/stores/project/tasks.ts | 5 +--- src/stores/project/workflow.ts | 5 +--- src/utils/time.ts | 7 +++--- 13 files changed, 48 insertions(+), 52 deletions(-) create mode 100644 src/i18n/i18n-helpers.ts diff --git a/src/composables/ai/aiShared.ts b/src/composables/ai/aiShared.ts index 643ab7e..d836e24 100644 --- a/src/composables/ai/aiShared.ts +++ b/src/composables/ai/aiShared.ts @@ -13,13 +13,11 @@ import { aiApi } from '@/api' import { state } from '@/stores/ai' import { useAppSettingsStore } from '@/stores/appSettings' -import i18n from '@/i18n' +import { t } from '@/i18n/i18n-helpers' import type { AiToolCallInfo } from '@/api/types' const appSettings = useAppSettingsStore() -const t = ((i18n as any).global.t as (k: string, named?: Record) => string).bind((i18n as any).global) - /** * 解析 AI 回复语言(useAiSend.sendMessage / useAiContext.compressContext 共用)。 * diff --git a/src/composables/ai/useAiConversations.ts b/src/composables/ai/useAiConversations.ts index 9fc1ded..8ace172 100644 --- a/src/composables/ai/useAiConversations.ts +++ b/src/composables/ai/useAiConversations.ts @@ -10,14 +10,11 @@ import { state } from '@/stores/ai' import { notifyConversationChanged } from './useAiEvents' import { persistUiState } from './useAiPanel' import { nextMsgId } from './aiShared' -import i18n from '@/i18n' +import { t } from '@/i18n/i18n-helpers' import type { AiMessage, AiToolCallInfo } from '@/api/types' const appSettings = useAppSettingsStore() -// composable 无组件上下文,借全局 i18n 实例翻译错误文案(同 useAiSend/aiShared 模式) -const t = ((i18n as any).global.t as (k: string, named?: Record) => string).bind((i18n as any).global) - /** 拉取会话列表;首次加载时若 appSettings 仍有有效 active-conv 且当前无活跃对话则恢复 */ async function loadConversations() { try { diff --git a/src/composables/ai/useAiEvents.ts b/src/composables/ai/useAiEvents.ts index c88d357..26576b8 100644 --- a/src/composables/ai/useAiEvents.ts +++ b/src/composables/ai/useAiEvents.ts @@ -16,17 +16,12 @@ import { ref } from 'vue' import { aiApi } from '@/api' import { useAppSettingsStore } from '@/stores/appSettings' import { state } from '@/stores/ai' -import i18n from '@/i18n' +import { t } from '@/i18n/i18n-helpers' import { nextMsgId, findToolCall, startApprovalTimer, clearApprovalTimer, clearAllApprovalTimers } from './aiShared' import { resetStreamWatchdog, clearStreamWatchdog } from './useAiStream' import { loadConversations } from './useAiConversations' import type { AiChatEvent, AiMessage, AiToolCallInfo } from '@/api/types' -// composable 内非组件上下文(无 setup),用 vue-i18n 全局实例的 t 而非 useI18n()。 -// 通过 any 中转规避 vue-i18n 深度 message schema 泛型导致的 TS2589(类型实例化过深)。 -// CR-30-2: 签名放宽支持插值参数(复用现有 t('ai.xxx', {...}) 模式,如 aiShared.ts:75)。 -const t = ((i18n as any).global.t as (key: string, params?: Record) => string).bind((i18n as any).global) - let _unlistenAiEvent: (() => void) | null = null let _unlistenConvChanged: (() => void) | null = null // AE-2025-06: onStreamTimeout 广播的审批计时器清理事件 unlistener diff --git a/src/composables/ai/useAiSend.ts b/src/composables/ai/useAiSend.ts index b79652b..8dc4731 100644 --- a/src/composables/ai/useAiSend.ts +++ b/src/composables/ai/useAiSend.ts @@ -21,13 +21,11 @@ import { ref } from 'vue' import { aiApi } from '@/api' import { state } from '@/stores/ai' import type { ContentPart, AiMessage } from '@/api/types' -import i18n from '@/i18n' +import { t } from '@/i18n/i18n-helpers' import { resetStreamWatchdog, clearStreamWatchdog } from './useAiStream' import { startListener } from './useAiEvents' import { nextMsgId, findToolCall, startApprovalTimer, clearApprovalTimer, clearAllApprovalTimers, resolveAiLang } from './aiShared' -const t = ((i18n as any).global.t as (k: string, named?: Record) => string).bind((i18n as any).global) - /// 待发送队列上限(超过抛错提示用户) const QUEUE_LIMIT = 10 diff --git a/src/composables/ai/useAiStream.ts b/src/composables/ai/useAiStream.ts index 24accc0..ade03b5 100644 --- a/src/composables/ai/useAiStream.ts +++ b/src/composables/ai/useAiStream.ts @@ -12,14 +12,10 @@ //! 循环依赖;下沉到 aiShared 后本模块不再 import useAiEvents,环消除) import { state } from '@/stores/ai' -import i18n from '@/i18n' +import { t } from '@/i18n/i18n-helpers' import { nextMsgId } from './aiShared' import { emit } from '@tauri-apps/api/event' -// composable 内非组件上下文(无 setup),用 vue-i18n 全局实例的 t 而非 useI18n()。 -// 通过 any 中转规避 vue-i18n 深度 message schema 泛型导致的 TS2589(类型实例化过深)。 -const t = ((i18n as any).global.t as (key: string) => string).bind((i18n as any).global) - /// ≥ 后端 STREAM_IDLE_TIMEOUT(120s, ai.rs:848)+余量; /// 前端若短于后端,慢首 token 会被前端先误杀 export const STREAM_TIMEOUT_MS = 130000 diff --git a/src/composables/ai/useToolCard.ts b/src/composables/ai/useToolCard.ts index e9ffca7..94154ba 100644 --- a/src/composables/ai/useToolCard.ts +++ b/src/composables/ai/useToolCard.ts @@ -11,22 +11,18 @@ //! 及原