重构: 前端DRY(style全局沉淀 + ts/js公共沉淀)
style-dry: - 新增 src/styles/components.css: .info-item*/.panel/.panel-header/.tech-tag/.card-tags 全局 - main.ts 注册 import - 删重复: ProjectDetail/TaskDetail/TaskOutputCard/ProjectCard/Projects(scoped删重复, 全局对子组件生效) - 未使用清理: Projects .card-progress dead(1处保守核对) tsjs-dry: - aiShared.ts: resolveAiLang(合并useAiSend.resolveLang + useAiContext.resolveLanguage) - stores/knowledge.ts: kindText/kindLabel/kindIcon/knowledgeStatusLabel/knowledgeConfidenceLabel(5公共) - 删重复: useAiSend/useAiContext(resolveLang) + Knowledge/KnowledgeDetail(4+5 helper) + ActiveProjectsPanel(formatLastActivity→formatRelativeZh复用) strategy: DRY收口, 公共沉淀(utils/store/shared); relativeTime非纯重复保留; .btn/.empty-hint局部override WATCH未动
This commit is contained in:
@@ -12,11 +12,30 @@
|
||||
|
||||
import { aiApi } from '@/api'
|
||||
import { state } from '@/stores/ai'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import i18n from '@/i18n'
|
||||
import type { AiToolCallInfo } from '@/api/types'
|
||||
|
||||
const appSettings = useAppSettingsStore()
|
||||
|
||||
const t = ((i18n as any).global.t as (k: string, named?: Record<string, unknown>) => string).bind((i18n as any).global)
|
||||
|
||||
/**
|
||||
* 解析 AI 回复语言(useAiSend.sendMessage / useAiContext.compressContext 共用)。
|
||||
*
|
||||
* df-ai-language='auto' → 回落到 df-language(应用主语言);否则用 df-ai-language 指定值;
|
||||
* 兜底 'zh-CN'。
|
||||
*
|
||||
* 原分别在 useAiSend.resolveLang(三元)与 useAiContext.resolveLanguage(if/else)各一份,
|
||||
* 语义相同仅写法不同,提取至此共用。
|
||||
*/
|
||||
export function resolveAiLang(): string {
|
||||
const raw = appSettings.get<string>('df-ai-language', 'auto')
|
||||
return raw === 'auto'
|
||||
? appSettings.get<string>('df-language', 'zh-CN')
|
||||
: raw
|
||||
}
|
||||
|
||||
/** 客户端消息自增 id(全局唯一,多个 composable 共用 nextMsgId) */
|
||||
let _msgCounter = 0
|
||||
|
||||
|
||||
@@ -24,15 +24,13 @@
|
||||
//! 耦合:
|
||||
//! - aiApi.clearContext / aiApi.compressContext(IPC)
|
||||
//! - state.activeConversationId(读当前对话)
|
||||
//! - appSettings.get(df-ai-language/df-language)(压缩语言;与 useAiSend.sendMessage 同源)
|
||||
//! - resolveAiLang(压缩语言;与 useAiSend.sendMessage 同源,实现在 aiShared)
|
||||
|
||||
import { ref } from 'vue'
|
||||
import { listen, type UnlistenFn } from '@tauri-apps/api/event'
|
||||
import { aiApi } from '@/api'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { state } from '@/stores/ai'
|
||||
|
||||
const appSettings = useAppSettingsStore()
|
||||
import { resolveAiLang } from './aiShared'
|
||||
|
||||
/// 压缩中 loading(防重复点击;AiCompressing→true / AiCompressed|AiError→false)
|
||||
const isCompressing = ref(false)
|
||||
@@ -108,20 +106,6 @@ function stopContextListener(): void {
|
||||
_callbacks = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析压缩语言(与 useAiSend.sendMessage 同源逻辑):
|
||||
* - df-ai-language='auto' → df-language(应用主语言)
|
||||
* - 否则用 df-ai-language 指定值
|
||||
* - 兜底 'zh-CN'
|
||||
*/
|
||||
function resolveLanguage(): string {
|
||||
const raw = appSettings.get<string>('df-ai-language', 'auto')
|
||||
if (raw === 'auto') {
|
||||
return appSettings.get<string>('df-language', 'zh-CN')
|
||||
}
|
||||
return raw
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩当前对话上下文。
|
||||
*
|
||||
@@ -136,7 +120,7 @@ async function compressContext(): Promise<void> {
|
||||
if (isCompressing.value) return // 防重复点击
|
||||
isCompressing.value = true
|
||||
try {
|
||||
await aiApi.compressContext(convId, resolveLanguage())
|
||||
await aiApi.compressContext(convId, resolveAiLang())
|
||||
// 后端 IPC 同步等到 LLM 压缩完成才 resolve(非 spawn 异步),成功即复位 isCompressing;
|
||||
// case 'AiCompressed' 事件也复位(双保险,防事件丢失致按钮永久禁用)
|
||||
isCompressing.value = false
|
||||
|
||||
@@ -19,31 +19,15 @@ import { listen } from '@tauri-apps/api/event'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { ref } from 'vue'
|
||||
import { aiApi } from '@/api'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { state } from '@/stores/ai'
|
||||
import type { ContentPart, AiMessage } from '@/api/types'
|
||||
import i18n from '@/i18n'
|
||||
import { resetStreamWatchdog, clearStreamWatchdog } from './useAiStream'
|
||||
import { startListener } from './useAiEvents'
|
||||
import { nextMsgId, findToolCall, startApprovalTimer, clearApprovalTimer, clearAllApprovalTimers } from './aiShared'
|
||||
import { nextMsgId, findToolCall, startApprovalTimer, clearApprovalTimer, clearAllApprovalTimers, resolveAiLang } from './aiShared'
|
||||
|
||||
const t = ((i18n as any).global.t as (k: string, named?: Record<string, unknown>) => string).bind((i18n as any).global)
|
||||
|
||||
const appSettings = useAppSettingsStore()
|
||||
|
||||
/**
|
||||
* B-260617-03 DRY: 解析 AI 回复语言。
|
||||
*
|
||||
* df-ai-language='auto' → 回落到 df-language;否则用 df-ai-language 指定值。
|
||||
* doSend/regenerate/editMessage 三处复用(原各内联同一段表达式)。
|
||||
*/
|
||||
function resolveLang(): string {
|
||||
const raw = appSettings.get<string>('df-ai-language', 'auto')
|
||||
return raw === 'auto'
|
||||
? appSettings.get<string>('df-language', 'zh-CN')
|
||||
: raw
|
||||
}
|
||||
|
||||
/// 待发送队列上限(超过抛错提示用户)
|
||||
const QUEUE_LIMIT = 10
|
||||
|
||||
@@ -114,7 +98,7 @@ async function doSend(text: string, skill?: string, force = false, parts?: Conte
|
||||
resetStreamWatchdog() // 启动流式看门狗,无数据超时兜底
|
||||
|
||||
await startListener()
|
||||
const lang = resolveLang()
|
||||
const lang = resolveAiLang()
|
||||
try {
|
||||
// force=true 走 force_send IPC(复位残留 generating),否则走正常 send
|
||||
// F-01 阶段6: 透传 modelOverride(主对话专用,后端兜底校验池内才用)
|
||||
@@ -170,7 +154,7 @@ async function regenerate() {
|
||||
resetStreamWatchdog()
|
||||
|
||||
await startListener()
|
||||
const lang = resolveLang()
|
||||
const lang = resolveAiLang()
|
||||
const convId = state.activeConversationId
|
||||
if (!convId) {
|
||||
// 无活跃对话:回滚占位,报错
|
||||
@@ -240,7 +224,7 @@ async function editMessage(newMessage: string) {
|
||||
resetStreamWatchdog()
|
||||
|
||||
await startListener()
|
||||
const lang = resolveLang()
|
||||
const lang = resolveAiLang()
|
||||
const convId = state.activeConversationId
|
||||
if (!convId) {
|
||||
state.streaming = false
|
||||
|
||||
Reference in New Issue
Block a user