This commit is contained in:
2026-04-20 13:14:43 -04:00
parent 17b91d6ac8
commit 53f078154e
10 changed files with 103 additions and 100 deletions

View File

@@ -7,12 +7,14 @@ import {
ShieldCheck, RotateCcw
} from 'lucide-vue-next';
import {
useSettingsStore,
useSettingsStore,
} from '../stores/settings';
import {
LANGUAGES,
SPEAKER_IDENTITY_OPTIONS,
TONE_REGISTER_OPTIONS,
type Participant
} from '../stores/settings';
} from '../domain/translation';
import { useConversationStore } from '../stores/conversation';
import { useLogsStore } from '../stores/logs';
import { cn } from '../lib/utils';

View File

@@ -2,7 +2,7 @@
import { ref, computed, watch } from 'vue';
import { Clock, Search, ArrowRightLeft, Trash2, User, Type, Copy, Check, FileText } from 'lucide-vue-next';
import { useHistoryStore } from '../stores/history';
import { SPEAKER_IDENTITY_OPTIONS, TONE_REGISTER_OPTIONS } from '../stores/settings';
import { SPEAKER_IDENTITY_OPTIONS, TONE_REGISTER_OPTIONS } from '../domain/translation';
import { cn } from '../lib/utils';
import { useClipboard } from '../composables/useClipboard';

View File

@@ -8,9 +8,9 @@ import {
DEFAULT_REFINEMENT_TEMPLATE,
CONVERSATION_SYSTEM_PROMPT_TEMPLATE,
CONVERSATION_EVALUATION_PROMPT_TEMPLATE,
CONVERSATION_REFINEMENT_PROMPT_TEMPLATE,
type ApiProfile
CONVERSATION_REFINEMENT_PROMPT_TEMPLATE
} from '../stores/settings';
import type { ApiProfile } from '../domain/translation';
import { cn } from '../lib/utils';
import HistoryView from './HistoryView.vue';
import LogsView from './LogsView.vue';

View File

@@ -3,7 +3,8 @@ import { ref, computed, onMounted, onUnmounted } from 'vue';
import { storeToRefs } from 'pinia';
import { ChevronDown, Check, ArrowRightLeft, Trash2, FileText, Plus, Loader2, Send, User, Type, Copy, Save } from 'lucide-vue-next';
import { listen } from '@tauri-apps/api/event';
import { useSettingsStore, LANGUAGES, SPEAKER_IDENTITY_OPTIONS, TONE_REGISTER_OPTIONS } from '../stores/settings';
import { LANGUAGES, SPEAKER_IDENTITY_OPTIONS, TONE_REGISTER_OPTIONS } from '../domain/translation';
import { useSettingsStore } from '../stores/settings';
import { useHistoryStore } from '../stores/history';
import { useLogsStore } from '../stores/logs';
import { useTranslationWorkspaceStore } from '../stores/translation-workspace';

89
src/domain/translation.ts Normal file
View File

@@ -0,0 +1,89 @@
export interface Language {
displayName: string;
englishName: string;
code: string;
}
export const LANGUAGES: Language[] = [
{ displayName: '中文(简体)', englishName: 'Simplified Chinese', code: 'zh-Hans' },
{ displayName: '中文(繁体)', englishName: 'Traditional Chinese', code: 'zh-Hant' },
{ displayName: '英语(美国)', englishName: 'American English', code: 'en-US' },
{ displayName: '英语(英国)', englishName: 'British English', code: 'en-GB' },
{ displayName: '西班牙语', englishName: 'Spanish', code: 'es' },
{ displayName: '葡萄牙语', englishName: 'Portuguese', code: 'pt' },
{ displayName: '日语', englishName: 'Japanese', code: 'ja' },
{ displayName: '韩语', englishName: 'Korean', code: 'ko' },
{ displayName: '法语', englishName: 'French', code: 'fr' },
{ displayName: '德语', englishName: 'German', code: 'de' },
{ displayName: '意大利语', englishName: 'Italian', code: 'it' },
{ displayName: '俄语', englishName: 'Russian', code: 'ru' },
{ displayName: '越南语', englishName: 'Vietnamese', code: 'vi' },
{ displayName: '泰语', englishName: 'Thai', code: 'th' },
{ displayName: '阿拉伯语', englishName: 'Arabic', code: 'ar' },
];
export const SPEAKER_IDENTITY_OPTIONS = [
{ label: '男性', value: 'Male' },
{ label: '女性', value: 'Female' },
{ label: '中性', value: 'Gender-neutral' },
] as const;
export const TONE_REGISTER_OPTIONS = [
{ label: '自动识别', value: 'Auto-detect', description: '分析并保持原文的语气、情绪和礼貌程度' },
{ label: '正式专业', value: 'Formal & Professional', description: '商务邮件、法律合同、官方报告' },
{ label: '礼貌客气', value: 'Polite & Respectful', description: '与长辈、客户或初次见面的人交流' },
{ label: '礼貌随和', value: 'Polite & Conversational', description: '得体但不刻板的日常对话' },
{ label: '中性标准', value: 'Neutral & Standard', description: '维基百科、说明书、客观的新闻报道' },
{ label: '非正式', value: 'Casual & Informal', description: '朋友聊天、社交媒体、非正式简讯' },
{ label: '亲切友好', value: 'Warm & Friendly', description: '社区信函、给朋友的建议、温馨提示' },
{ label: '严谨权威', value: 'Strict & Authoritative', description: '警示标志、强制规定、上级指令' },
{ label: '热情生动', value: 'Enthusiastic & Vivid', description: '广告文案、旅游推荐、博主推文' },
] as const;
export interface ApiProfile {
id: string;
name: string;
apiBaseUrl: string;
apiKey: string;
modelName: string;
}
export interface HistoryItem {
id: string;
timestamp: string;
sourceLang: Language;
targetLang: Language;
sourceText: string;
targetText: string;
context: string;
speakerIdentity: string;
toneRegister: string;
modelName: string;
}
export interface Participant {
name: string;
gender: string;
language: Language;
tone: string;
}
export interface ChatMessage {
id: string;
sender: 'me' | 'partner';
original: string;
translated: string;
timestamp: string;
evaluation?: string;
isEvaluating?: boolean;
isRefining?: boolean;
}
export interface ChatSession {
id: string;
title: string;
me: Participant;
partner: Participant;
messages: ChatMessage[];
lastActivity: string;
}

View File

@@ -1,4 +1,4 @@
import type { Language, Participant } from '../stores/settings';
import type { Language, Participant } from '../domain/translation';
interface SingleTranslationPromptContext {
sourceLang: Language;

View File

@@ -1,5 +1,5 @@
import { invoke } from '@tauri-apps/api/core';
import type { ApiProfile } from '../stores/settings';
import type { ApiProfile } from '../domain/translation';
interface Message {
role: string;

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { useLocalStorage } from '@vueuse/core';
import type { ChatMessage, ChatSession, Participant } from './settings';
import type { ChatMessage, ChatSession, Participant } from '../domain/translation';
function formatTimestamp() {
const now = new Date();

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia';
import { useLocalStorage } from '@vueuse/core';
import type { HistoryItem } from './settings';
import type { HistoryItem } from '../domain/translation';
function formatTimestamp() {
const now = new Date();

View File

@@ -1,48 +1,7 @@
import { computed } from 'vue';
import { defineStore } from 'pinia';
import { useLocalStorage } from '@vueuse/core';
export interface Language {
displayName: string; // UI 显示的中文名,如 "英语(英国)"
englishName: string; // 文件中的第二列,用于 {SOURCE_LANG}
code: string; // 文件中的第一列,用于 {SOURCE_CODE}
}
export const LANGUAGES: Language[] = [
{ displayName: '中文(简体)', englishName: 'Simplified Chinese', code: 'zh-Hans' },
{ displayName: '中文(繁体)', englishName: 'Traditional Chinese', code: 'zh-Hant' },
{ displayName: '英语(美国)', englishName: 'American English', code: 'en-US' },
{ displayName: '英语(英国)', englishName: 'British English', code: 'en-GB' },
{ displayName: '西班牙语', englishName: 'Spanish', code: 'es' },
{ displayName: '葡萄牙语', englishName: 'Portuguese', code: 'pt' },
{ displayName: '日语', englishName: 'Japanese', code: 'ja' },
{ displayName: '韩语', englishName: 'Korean', code: 'ko' },
{ displayName: '法语', englishName: 'French', code: 'fr' },
{ displayName: '德语', englishName: 'German', code: 'de' },
{ displayName: '意大利语', englishName: 'Italian', code: 'it' },
{ displayName: '俄语', englishName: 'Russian', code: 'ru' },
{ displayName: '越南语', englishName: 'Vietnamese', code: 'vi' },
{ displayName: '泰语', englishName: 'Thai', code: 'th' },
{ displayName: '阿拉伯语', englishName: 'Arabic', code: 'ar' },
];
export const SPEAKER_IDENTITY_OPTIONS = [
{ label: '男性', value: 'Male' },
{ label: '女性', value: 'Female' },
{ label: '中性', value: 'Gender-neutral' },
];
export const TONE_REGISTER_OPTIONS = [
{ label: '自动识别', value: 'Auto-detect', description: '分析并保持原文的语气、情绪和礼貌程度' },
{ label: '正式专业', value: 'Formal & Professional', description: '商务邮件、法律合同、官方报告' },
{ label: '礼貌客气', value: 'Polite & Respectful', description: '与长辈、客户或初次见面的人交流' },
{ label: '礼貌随和', value: 'Polite & Conversational', description: '得体但不刻板的日常对话' },
{ label: '中性标准', value: 'Neutral & Standard', description: '维基百科、说明书、客观的新闻报道' },
{ label: '非正式', value: 'Casual & Informal', description: '朋友聊天、社交媒体、非正式简讯' },
{ label: '亲切友好', value: 'Warm & Friendly', description: '社区信函、给朋友的建议、温馨提示' },
{ label: '严谨权威', value: 'Strict & Authoritative', description: '警示标志、强制规定、上级指令' },
{ label: '热情生动', value: 'Enthusiastic & Vivid', description: '广告文案、旅游推荐、博主推文' },
];
import { LANGUAGES, SPEAKER_IDENTITY_OPTIONS, TONE_REGISTER_OPTIONS, type ApiProfile, type Language } from '../domain/translation';
export const DEFAULT_TEMPLATE = `You are a professional {SOURCE_LANG} ({SOURCE_CODE}) to {TARGET_LANG} ({TARGET_CODE}) translator. Your goal is to accurately convey the meaning and nuances of the original {SOURCE_LANG} text while adhering to {TARGET_LANG} grammar, vocabulary, and cultural sensitivities.
@@ -106,54 +65,6 @@ export const DEFAULT_REFINEMENT_TEMPLATE = `You are a senior translation editor.
4. If a piece of feedback contradicts the [Source Text], prioritize accuracy and provide a balanced refinement.
5. Produce ONLY the refined {TARGET_LANG} translation, without any additional explanations, notes, or commentary.`;
export interface ApiProfile {
id: string;
name: string;
apiBaseUrl: string;
apiKey: string;
modelName: string;
}
export interface HistoryItem {
id: string;
timestamp: string;
sourceLang: Language;
targetLang: Language;
sourceText: string;
targetText: string;
context: string;
speakerIdentity: string;
toneRegister: string;
modelName: string;
}
export interface Participant {
name: string;
gender: string;
language: Language;
tone: string;
}
export interface ChatMessage {
id: string;
sender: 'me' | 'partner';
original: string;
translated: string;
timestamp: string;
evaluation?: string; // AI 审计结果 (JSON 字符串)
isEvaluating?: boolean; // 审计状态
isRefining?: boolean; // 润色状态
}
export interface ChatSession {
id: string;
title: string;
me: Participant;
partner: Participant;
messages: ChatMessage[];
lastActivity: string;
}
export const CONVERSATION_SYSTEM_PROMPT_TEMPLATE = `# Role: Professional Real-time Conversation Translator
# Participants: