完善一些提示性内容
This commit is contained in:
parent
6eb2fc18b3
commit
5f5255830f
59
src/App.vue
59
src/App.vue
@ -67,17 +67,20 @@ const translationConfig = ref<TranslationConfig>({
|
||||
apiBase: localStorage.getItem('llm.apiBase') ?? 'https://open.bigmodel.cn/api/paas/v4',
|
||||
apiKey: localStorage.getItem('llm.apiKey') ?? '',
|
||||
model: localStorage.getItem('llm.model') ?? 'GLM-4.7-Flash',
|
||||
batchSize: Number(localStorage.getItem('llm.batchSize') ?? '60'),
|
||||
batchSize: Number(localStorage.getItem('llm.batchSize') ?? '12'),
|
||||
contextSize: Number(localStorage.getItem('llm.contextSize') ?? '5'),
|
||||
})
|
||||
const pending = ref(false)
|
||||
const feedback = ref('')
|
||||
const feedbackTone = ref<'normal' | 'error'>('normal')
|
||||
const showAdvanced = ref(false)
|
||||
const isDragging = ref(false)
|
||||
const showApiKeyDialog = ref(false)
|
||||
const apiKeyUrlCopied = ref(false)
|
||||
const authorUrlCopied = ref(false)
|
||||
let unlistenMenuAction: UnlistenFn | null = null
|
||||
let dragDropUnlistenFn: UnlistenFn | null = null
|
||||
let authorCopyTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const selectedTask = computed(() => taskStore.selectedTask)
|
||||
const hasTranslationKey = computed(() => translationConfig.value.apiKey.trim().length > 0)
|
||||
@ -98,10 +101,29 @@ onUnmounted(() => {
|
||||
dragDropUnlistenFn()
|
||||
dragDropUnlistenFn = null
|
||||
}
|
||||
if (authorCopyTimer) {
|
||||
clearTimeout(authorCopyTimer)
|
||||
authorCopyTimer = null
|
||||
}
|
||||
})
|
||||
|
||||
watch(locale, (newLocale) => {
|
||||
localStorage.setItem('locale', newLocale)
|
||||
if (outputMode.value === 'translate' && !hasTranslationKey.value) {
|
||||
showMissingApiKeyFeedback()
|
||||
}
|
||||
})
|
||||
|
||||
watch([outputMode, hasTranslationKey], ([mode, hasKey]) => {
|
||||
if (mode === 'translate' && !hasKey) {
|
||||
showMissingApiKeyFeedback()
|
||||
return
|
||||
}
|
||||
|
||||
if (feedbackTone.value === 'error' && feedback.value === t('app.feedback.noApiKey')) {
|
||||
feedbackTone.value = 'normal'
|
||||
feedback.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
function persistTranslationConfig() {
|
||||
@ -115,9 +137,15 @@ function persistTranslationConfig() {
|
||||
function resetModelPaths() {
|
||||
whisperModelPath.value = defaultModelPaths.value?.whisperModelPath ?? ''
|
||||
vadModelPath.value = defaultModelPaths.value?.vadModelPath ?? ''
|
||||
feedbackTone.value = 'normal'
|
||||
feedback.value = t('app.feedback.restoredDefaults')
|
||||
}
|
||||
|
||||
function showMissingApiKeyFeedback() {
|
||||
feedbackTone.value = 'error'
|
||||
feedback.value = t('app.feedback.noApiKey')
|
||||
}
|
||||
|
||||
function freeApiKeyHint() {
|
||||
if (locale.value === 'zh-CN') {
|
||||
return '开始翻译任务前需要先填写 LLM API Key。你可以选择下面任意一种方式。'
|
||||
@ -127,7 +155,7 @@ function freeApiKeyHint() {
|
||||
}
|
||||
|
||||
function openApiKeyDialog() {
|
||||
feedback.value = t('app.feedback.noApiKey')
|
||||
showMissingApiKeyFeedback()
|
||||
apiKeyUrlCopied.value = false
|
||||
showApiKeyDialog.value = true
|
||||
}
|
||||
@ -137,6 +165,18 @@ async function copyFreeApiKeyUrl() {
|
||||
apiKeyUrlCopied.value = true
|
||||
}
|
||||
|
||||
async function copyAuthorUrl() {
|
||||
await navigator.clipboard.writeText('https://kuraa.cc')
|
||||
authorUrlCopied.value = true
|
||||
if (authorCopyTimer) {
|
||||
clearTimeout(authorCopyTimer)
|
||||
}
|
||||
authorCopyTimer = setTimeout(() => {
|
||||
authorUrlCopied.value = false
|
||||
authorCopyTimer = null
|
||||
}, 1400)
|
||||
}
|
||||
|
||||
function acknowledgeApiKeyDialog() {
|
||||
showApiKeyDialog.value = false
|
||||
outputMode.value = 'source'
|
||||
@ -202,6 +242,7 @@ async function submitFiles(filePaths: string[]) {
|
||||
}
|
||||
|
||||
pending.value = true
|
||||
feedbackTone.value = 'normal'
|
||||
feedback.value = ''
|
||||
|
||||
try {
|
||||
@ -227,6 +268,7 @@ async function submitFiles(filePaths: string[]) {
|
||||
|
||||
async function handlePickFiles() {
|
||||
try {
|
||||
feedbackTone.value = 'normal'
|
||||
feedback.value = ''
|
||||
persistTranslationConfig()
|
||||
const selected = await open({
|
||||
@ -336,11 +378,13 @@ async function handleExport(format: 'srt' | 'vtt' | 'ass') {
|
||||
async function handleRetryTranslate(taskId: string) {
|
||||
persistTranslationConfig()
|
||||
if (!translationConfig.value.apiKey.trim()) {
|
||||
feedbackTone.value = 'error'
|
||||
feedback.value = t('app.feedback.noApiKey')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await taskStore.retryTranslation(taskId, translationConfig.value)
|
||||
feedbackTone.value = 'normal'
|
||||
feedback.value = t('app.feedback.translationStarted')
|
||||
} catch (error) {
|
||||
feedback.value = error instanceof Error ? error.message : t('app.feedback.translationFailed')
|
||||
@ -388,8 +432,8 @@ async function handleTranslateFromEditor() {
|
||||
<span>
|
||||
{{ locale === 'zh-CN' ? '推荐免费的' : 'Recommended free option:' }}
|
||||
<button class="api-key-link" type="button" @click="copyFreeApiKeyUrl">GLM-4.7-Flash</button>
|
||||
<span v-if="apiKeyUrlCopied" class="copy-hint">
|
||||
{{ locale === 'zh-CN' ? '已复制链接' : 'Link copied' }}
|
||||
<span class="copy-hint" :class="{ copied: apiKeyUrlCopied }">
|
||||
{{ apiKeyUrlCopied ? (locale === 'zh-CN' ? '已复制链接' : 'Link copied') : (locale === 'zh-CN' ? '点击复制申请链接' : 'click to copy link') }}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
@ -399,7 +443,7 @@ async function handleTranslateFromEditor() {
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<button class="button" type="button" @click="acknowledgeApiKeyDialog">
|
||||
{{ locale === 'zh-CN' ? '明白了' : 'Got it' }}
|
||||
{{ locale === 'zh-CN' ? '明白了,先转原文' : 'Got it, use source mode' }}
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
@ -410,7 +454,8 @@ async function handleTranslateFromEditor() {
|
||||
<div class="toolbar-title">
|
||||
<strong>CrossSubtitle</strong>
|
||||
<span class="credit-line">
|
||||
by <a href="https://kuraa.cc" target="_blank" rel="noreferrer">kuraa</a>
|
||||
by <button class="author-link" type="button" @click="copyAuthorUrl">kuraa</button>
|
||||
<span v-if="authorUrlCopied" class="author-copy-hint">🎉</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
@ -460,7 +505,7 @@ async function handleTranslateFromEditor() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p v-if="feedback" class="feedback status-text">{{ feedback }}</p>
|
||||
<p v-if="feedback" class="feedback status-text" :class="{ error: feedbackTone === 'error' }">{{ feedback }}</p>
|
||||
</div>
|
||||
|
||||
<div v-if="showAdvanced" class="advanced-shell">
|
||||
|
||||
@ -157,17 +157,27 @@ textarea {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.credit-line a {
|
||||
.credit-line a,
|
||||
.author-link {
|
||||
color: var(--c-text);
|
||||
background: transparent;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: border-color var(--transition);
|
||||
}
|
||||
|
||||
.credit-line a:hover {
|
||||
.credit-line a:hover,
|
||||
.author-link:hover {
|
||||
border-bottom-color: var(--c-text);
|
||||
}
|
||||
|
||||
.author-copy-hint {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.workspace-toolbar,
|
||||
.advanced-shell {
|
||||
margin-top: 16px;
|
||||
@ -332,6 +342,11 @@ textarea {
|
||||
margin: 12px 0 0;
|
||||
}
|
||||
|
||||
.status-text.error {
|
||||
color: var(--c-error);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.content-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 300px minmax(0, 1fr);
|
||||
@ -950,6 +965,8 @@ textarea {
|
||||
|
||||
.api-key-dialog {
|
||||
width: min(520px, 100%);
|
||||
max-height: calc(100vh - 40px);
|
||||
overflow: auto;
|
||||
padding: 20px;
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: var(--radius-lg);
|
||||
@ -1109,10 +1126,14 @@ textarea {
|
||||
}
|
||||
|
||||
.copy-hint {
|
||||
color: var(--c-success);
|
||||
color: var(--c-text-tertiary);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.copy-hint.copied {
|
||||
color: var(--c-success);
|
||||
}
|
||||
|
||||
.dialog-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user