From 939a0a46cdc54caee2925449ec886f81334fb75c Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Sun, 5 Apr 2026 11:17:00 -0400 Subject: [PATCH] optimize chat audit --- src/components/ConversationView.vue | 242 +++++++++++++++++++--------- 1 file changed, 165 insertions(+), 77 deletions(-) diff --git a/src/components/ConversationView.vue b/src/components/ConversationView.vue index 4a6b092..c1d31b9 100644 --- a/src/components/ConversationView.vue +++ b/src/components/ConversationView.vue @@ -4,7 +4,7 @@ import { Plus, Search, Trash2, Send, User, Type, ChevronDown, Check, MessageSquare, Loader2, Copy, X, Sparkles, Languages, Venus, Mars, CircleSlash, - ShieldCheck, TriangleAlert, AlertCircle + ShieldCheck } from 'lucide-vue-next'; import { useSettingsStore, @@ -43,6 +43,16 @@ const newSessionPartner = ref({ tone: 'Auto-detect' }); +// Audit Modal States +const isAuditModalOpen = ref(false); +const currentAuditMessageId = ref(null); +const selectedSuggestionIds = ref([]); + +const activeAuditMessage = computed(() => { + if (!activeSession.value || !currentAuditMessageId.value) return null; + return activeSession.value.messages.find(m => m.id === currentAuditMessageId.value) || null; +}); + // Custom Dropdown States for Modal const meLangDropdownOpen = ref(false); const meGenderDropdownOpen = ref(false); @@ -211,7 +221,15 @@ const translateMessage = async (sender: 'me' | 'partner') => { const evaluateMessage = async (messageId: string) => { if (!activeSession.value) return; const msg = activeSession.value.messages.find(m => m.id === messageId); - if (!msg || msg.isEvaluating) return; + if (!msg) return; + + currentAuditMessageId.value = messageId; + selectedSuggestionIds.value = []; + + await nextTick(); + isAuditModalOpen.value = true; + + if (msg.evaluation || msg.isEvaluating) return; settings.updateChatMessage(activeSession.value.id, messageId, { isEvaluating: true }); @@ -264,10 +282,15 @@ const evaluateMessage = async (messageId: string) => { settings.addLog('error', String(err)); } finally { settings.updateChatMessage(activeSession.value.id, messageId, { isEvaluating: false }); - scrollToBottom(); } }; +const toggleSuggestion = (id: number) => { + const index = selectedSuggestionIds.value.indexOf(id); + if (index > -1) selectedSuggestionIds.value.splice(index, 1); + else selectedSuggestionIds.value.push(id); +}; + const refineMessage = async (messageId: string) => { if (!activeSession.value) return; const msg = activeSession.value.messages.find(m => m.id === messageId); @@ -275,11 +298,16 @@ const refineMessage = async (messageId: string) => { let evalData; try { - evalData = JSON.parse(msg.evaluation); + evalData = parseEvaluation(msg.evaluation); } catch (e) { return; } - const suggestionsText = evalData.suggestions.map((s: any) => `- ${s.text} (Importance: ${s.importance})`).join('\n'); + // 仅使用选中的建议 + const selectedSuggestions = evalData.suggestions.filter((s: any) => selectedSuggestionIds.value.includes(s.id)); + if (selectedSuggestions.length === 0) return; + const suggestionsText = selectedSuggestions.map((s: any) => `- ${s.text}`).join('\n'); + + isAuditModalOpen.value = false; // 关闭弹窗开始润色 settings.updateChatMessage(activeSession.value.id, messageId, { isRefining: true, translated: '' }); currentStreamingMessageId.value = messageId; @@ -292,6 +320,9 @@ const refineMessage = async (messageId: string) => { const myToneLabel = TONE_REGISTER_OPTIONS.find(o => o.value === activeSession.value!.me.tone)?.label || '随和'; + // 确定目标语气 + const targetTone = msg.sender === 'me' ? myToneLabel : '自动识别 (保持原作者原始语气和情绪)'; + const systemPrompt = CONVERSATION_REFINEMENT_PROMPT_TEMPLATE .replace(/{ME_NAME}/g, activeSession.value.me.name) .replace(/{ME_GENDER}/g, activeSession.value.me.gender) @@ -302,7 +333,7 @@ const refineMessage = async (messageId: string) => { .replace(/{HISTORY_BLOCK}/g, historyBlock || 'None') .replace(/{CURRENT_TRANSLATION}/g, msg.translated) .replace(/{SUGGESTIONS}/g, suggestionsText) - .replace(/{MY_TONE}/g, myToneLabel); + .replace(/{TARGET_TONE}/g, targetTone); const requestBody = { model: settings.modelName, @@ -351,18 +382,6 @@ const parseEvaluation = (evalStr?: string) => { } }; -const getSeverityColor = (importance: number) => { - if (importance >= 80) return 'text-red-500 bg-red-50 dark:bg-red-900/20 border-red-100 dark:border-red-900/30'; - if (importance >= 40) return 'text-amber-500 bg-amber-50 dark:bg-amber-900/20 border-amber-100 dark:border-amber-900/30'; - return 'text-blue-500 bg-blue-50 dark:bg-blue-900/20 border-blue-100 dark:border-blue-900/30'; -}; - -const getSeverityIcon = (importance: number) => { - if (importance >= 80) return AlertCircle; - if (importance >= 40) return TriangleAlert; - return ShieldCheck; -}; - const handleGlobalClick = () => { myToneDropdownOpen.value = false; closeAllModalDropdowns(); @@ -528,67 +547,8 @@ onUnmounted(() => window.removeEventListener('click', handleGlobalClick)); - - - - -
-
- -
-
- {{ parseEvaluation(msg.evaluation).score }} -
-

- {{ parseEvaluation(msg.evaluation).analysis }} -

-
- - -
-
- - {{ sug.text }} -
-
- - - -
-
-
@@ -869,7 +829,135 @@ onUnmounted(() => window.removeEventListener('click', handleGlobalClick)); + + + + +
+
+ +
+
+
+ +
+
+

翻译质量审计

+

Quality Audit & Refinement

+
+
+ +
+ + +
+ +
+
+
+
+

总体评价

+
+
+ {{ parseEvaluation(activeAuditMessage.evaluation).score }}/ 100 +
+
+ +
+ +

正在深度分析译文...

+
+ +
+

+ "{{ parseEvaluation(activeAuditMessage.evaluation).analysis }}" +

+
+
+ + +
+
+
+

修改建议 (点击勾选)

+
+ +
+
+
+ +
+ +
+

{{ sug.text }}

+ + +
+
+
+
+ {{ sug.importance }}% +
+
+
+
+
+
+ + +
+ + +
+
+
+