This commit is contained in:
2026-03-23 14:46:34 +08:00
parent 52e44bd857
commit d517c1573d
2 changed files with 157 additions and 35 deletions

View File

@@ -14,9 +14,19 @@
<div class="flex items-center justify-between mb-3">
<span class="font-medium text-gray-800">源文本</span>
<div class="flex gap-2">
<div class="flex items-center gap-2">
<label class="flex items-center gap-1 cursor-pointer">
<input type="radio" v-model="inputMode" value="bulk" class="w-4 h-4" />
<span class="text-sm text-gray-700">批量导入</span>
</label>
<label class="flex items-center gap-1 cursor-pointer">
<input type="radio" v-model="inputMode" value="individual" class="w-4 h-4" />
<span class="text-sm text-gray-700">单个编辑</span>
</label>
</div>
<button @click="addSentence"
class="px-3 py-1 text-sm bg-blue-100 text-blue-700 border border-blue-300 rounded hover:bg-blue-200">
新增一行
新增
</button>
<button @click="fetchPrologue" :disabled="isFetching || !isElectronEnv"
class="px-3 py-1 text-sm bg-purple-100 text-purple-700 border border-purple-300 rounded hover:bg-purple-200 disabled:opacity-50">
@@ -29,12 +39,32 @@
</div>
</div>
<textarea :value="bulkText || sentences.join('\n')" @input="handleBulkChange" @paste="handlePaste"
placeholder="每行一句打招呼内容..."
class="w-full h-32 p-3 border border-gray-300 rounded text-sm text-gray-900 resize-none focus:border-blue-500 focus:outline-none" />
<!-- 批量导入模式 -->
<div v-if="inputMode === 'bulk'">
<textarea :value="bulkText || sentences.join('\n')" @input="handleBulkChange"
@paste="handlePaste" placeholder="每行一句打招呼内容..."
class="w-full h-32 p-3 border border-gray-300 rounded text-sm text-gray-900 resize-none focus:border-blue-500 focus:outline-none" />
<div class="text-xs text-gray-500 mt-2">
提示: 每行一句可直接粘贴多行文本
<div class="text-xs text-gray-500 mt-2">
提示: 每行一句可直接粘贴多行文本
</div>
</div>
<!-- 单个编辑模式 -->
<div v-else class="space-y-3">
<div v-for="(sentence, index) in sentences" :key="index"
class="bg-white rounded border border-gray-200 p-3">
<div class="flex items-center justify-between mb-2">
<span class="text-xs text-gray-500">话术 {{ index + 1 }}</span>
<button @click="removeSentence(index)"
class="text-red-500 hover:text-red-700 text-sm">
删除
</button>
</div>
<textarea :value="sentence" @input="updateSentence($event.target.value, index)"
placeholder="输入打招呼内容(可包含多行)..."
class="w-full h-20 p-2 border border-gray-200 rounded text-sm text-gray-900 resize-none focus:border-blue-500 focus:outline-none" />
</div>
</div>
</div>
@@ -78,13 +108,15 @@
]">
{{ region }}
</div>
<div v-if="filteredRegions.length === 0" class="col-span-full text-center py-8 text-gray-400">
<div v-if="filteredRegions.length === 0"
class="col-span-full text-center py-8 text-gray-400">
未找到相关大区
</div>
</div>
<!-- 选中大区的语言预览 -->
<div v-if="selectedRegions.length > 0" class="mb-4 p-3 bg-blue-50 border border-blue-200 rounded">
<div v-if="selectedRegions.length > 0"
class="mb-4 p-3 bg-blue-50 border border-blue-200 rounded">
<div class="text-sm text-blue-800 font-medium mb-2">
选中 {{ selectedRegions.length }} 个大区将翻译以下 {{ selectedLanguages.length }} 种语言
</div>
@@ -112,7 +144,8 @@
<!-- 当前语言的翻译结果 -->
<div class="space-y-2 max-h-40 overflow-auto">
<template v-if="translations[activeTab]?.length">
<div v-for="(t, i) in translations[activeTab]" :key="i" class="flex items-center gap-2">
<div v-for="(t, i) in translations[activeTab]" :key="i"
class="flex items-center gap-2">
<input type="text" :value="t" @input="updateTranslation($event.target.value, i)"
class="flex-1 px-3 py-1.5 text-sm text-gray-900 border border-gray-300 rounded focus:border-blue-500 focus:outline-none" />
<div class="relative group/source">
@@ -141,22 +174,23 @@
</div>
</div>
</div>
</div>
<!-- 底部 -->
<div class="p-4 border-t border-gray-200 flex justify-between items-center">
<span class="text-xs text-gray-500">
{{ sentences.filter(Boolean).length }} · 选择 {{ selectedRegions.length }} 个大区 · {{
selectedLanguages.length }} 种语言
</span>
<div class="flex gap-3">
<button @click="onClose" class="px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg">
取消
</button>
<button @click="handleConfirm"
class="px-4 py-2 text-sm bg-blue-500 text-white rounded-lg hover:bg-blue-600">
确定
</button>
<!-- 底部 -->
<div class="p-4 border-t border-gray-200 flex justify-between items-center">
<span class="text-xs text-gray-500">
{{ sentences.filter(Boolean).length }} · 选择 {{ selectedRegions.length }} 个大区 · {{
selectedLanguages.length }} 种语言
</span>
<div class="flex gap-3">
<button @click="onClose"
class="px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg">
取消
</button>
<button @click="handleConfirm"
class="px-4 py-2 text-sm bg-blue-500 text-white rounded-lg hover:bg-blue-600">
确定
</button>
</div>
</div>
</div>
</div>
@@ -180,6 +214,7 @@ const REGION_LIST = getRegions()
const sentences = ref([''])
const bulkText = ref('')
const inputMode = ref('bulk') // 'bulk' 或 'individual'
const selectedRegions = ref([])
const translations = ref({})
const activeTab = ref('')
@@ -262,6 +297,7 @@ function loadFromStorage() {
if (data.translations) translations.value = data.translations
if (typeof data.needTranslate === 'boolean') needTranslate.value = data.needTranslate
if (data.activeTab) activeTab.value = data.activeTab
if (data.inputMode) inputMode.value = data.inputMode
} catch (e) {
console.error('加载本地数据失败:', e)
}
@@ -275,6 +311,7 @@ function saveToStorage() {
translations: translations.value,
needTranslate: needTranslate.value,
activeTab: activeTab.value,
inputMode: inputMode.value,
}))
}
@@ -285,6 +322,17 @@ const addSentence = () => {
sentences.value.push('')
}
const updateSentence = (value, index) => {
sentences.value[index] = value
}
const removeSentence = (index) => {
sentences.value.splice(index, 1)
if (sentences.value.length === 0) {
sentences.value.push('')
}
}
const handlePaste = (e) => {
// e.preventDefault() handled by Vue if needed but standard logic applies
// We can rely on @paste event
@@ -397,6 +445,7 @@ const handleTranslate = async () => {
try {
const result = await window.electronAPI.translate(joinedText, lang)
if (result.success) {
console.log(`翻译结果完整 ${lang} 成功:`, result)
let translatedLines = result.result.split('\n').map(s => s.trim())
if (translatedLines.length > 0) {