This commit is contained in:
Zyronon
2025-12-31 16:07:30 +08:00
committed by GitHub
parent 043edf7f39
commit d145c9ceca
8 changed files with 516 additions and 412 deletions

View File

@@ -6,6 +6,7 @@ import { getDefaultArticleWord, getDefaultDict } from "@/types/func.ts"
import { useSettingStore } from "@/stores/setting.ts"
import { useBaseStore } from "@/stores/base.ts"
import { useRuntimeStore } from "@/stores/runtime.ts"
import { nanoid } from 'nanoid'
function parseSentence(sentence: string) {
// 先统一一些常见的“智能引号” -> 直引号,避免匹配问题
@@ -368,7 +369,7 @@ export function syncBookInMyStudyList(study = false) {
if (!temp.custom && temp.id !== DictId.articleCollect) {
temp.custom = true
if (!temp.id.includes('_custom')) {
temp.id += '_custom'
temp.id += '_custom_' + nanoid(6)
}
}
temp.length = temp.articles.length

View File

@@ -50,6 +50,7 @@ import { getPracticeArticleCache, setPracticeArticleCache } from '@/utils/cache.
import { emitter, EventKey, useEvents } from '@/utils/eventBus.ts'
import { computed, onMounted, onUnmounted, provide, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { nanoid } from 'nanoid'
const store = useBaseStore()
const runtimeStore = useRuntimeStore()
@@ -354,7 +355,7 @@ function saveArticle(val: Article) {
setArticle(val)
store.sbook.custom = true
if (!store.sbook.id.includes('_custom')) {
store.sbook.id += '_custom'
store.sbook.id += '_custom_' + nanoid(6)
}
}

View File

@@ -2,17 +2,8 @@
import { Article, Sentence, TranslateEngine } from '@/types/types.ts'
import BaseButton from '@/components/BaseButton.vue'
import EditAbleText from '@/components/EditAbleText.vue'
import {
getNetworkTranslate,
getSentenceAllText,
getSentenceAllTranslateText,
} from '@/hooks/translate.ts'
import {
genArticleSectionData,
splitCNArticle2,
splitEnArticle2,
usePlaySentenceAudio,
} from '@/hooks/article.ts'
import { getNetworkTranslate, getSentenceAllText, getSentenceAllTranslateText } from '@/hooks/translate.ts'
import { genArticleSectionData, splitCNArticle2, splitEnArticle2, usePlaySentenceAudio } from '@/hooks/article.ts'
import { _nextTick, _parseLRC, cloneDeep, last } from '@/utils'
import { defineAsyncComponent, watch } from 'vue'
import Empty from '@/components/Empty.vue'
@@ -52,7 +43,7 @@ const emit = defineEmits<{
let networkTranslateEngine = $ref('baidu')
let progress = $ref(0)
let failCount = $ref(0)
let textareaRef = $ref<HTMLTextAreaElement>()
let resultRef = $ref<HTMLDivElement>()
const TranslateEngineOptions = [
// {value: 'youdao', label: '有道'},
{ value: 'baidu', label: '百度' },
@@ -67,6 +58,9 @@ watch(
progress = 0
failCount = 0
apply(false)
_nextTick(() => {
resultRef?.scrollTo(0,0)
})
},
{ immediate: true }
)
@@ -225,7 +219,7 @@ function handleChange(e: any) {
let s = lrcList[k]
// let d = Comparison.default.cosine.similarity(w.text, s.text)
// d = Comparison.default.levenshtein.similarity(w.text, s.text)
let d = Comparison.default.longestCommonSubsequence.similarity(w.text, s.text)
let d = Comparison.default.longestCommonSubsequence.similarity(w.text, s.text)
// d = Comparison.default.metricLcs.similarity(w.text, s.text)
// console.log(w.text, s.text, d)
if (d >= 0.8) {
@@ -309,10 +303,7 @@ function recordStart() {
sentenceAudioRef.play()
}
editSentence.audioPosition[0] = Number(sentenceAudioRef.currentTime.toFixed(2))
if (
editSentence.audioPosition[0] > editSentence.audioPosition[1] &&
editSentence.audioPosition[1] !== 0
) {
if (editSentence.audioPosition[0] > editSentence.audioPosition[1] && editSentence.audioPosition[1] !== 0) {
editSentence.audioPosition[1] = editSentence.audioPosition[0]
}
}
@@ -329,9 +320,7 @@ const { playSentenceAudio } = usePlaySentenceAudio()
function saveLrcPosition() {
// showEditAudioDialog = false
currentSentence.audioPosition = cloneDeep(editSentence.audioPosition)
editArticle.lrcPosition = editArticle.sections
.map((v, i) => v.map((w, j) => w.audioPosition ?? []))
.flat()
editArticle.lrcPosition = editArticle.sections.map((v, i) => v.map((w, j) => w.audioPosition ?? [])).flat()
}
function jumpAudio(time: number) {
@@ -414,17 +403,13 @@ function minusStartTime(val: Sentence) {
<ol class="py-0 pl-5 my-0 text-base color-main">
<li>复制原文然后分句</li>
<li>
点击 <span class="color-red font-bold">分句</span> 按钮进行自动分句<span
class="color-red font-bold"
>
点击 <span class="color-red font-bold">分句</span> 按钮进行自动分句<span class="color-red font-bold">
</span
>
手动编辑分句
</li>
<li>分句规则一行一句段落间空一行</li>
<li>
修改完成后点击 <span class="color-red font-bold">应用</span> 按钮同步到左侧结果栏
</li>
<li>修改完成后点击 <span class="color-red font-bold">应用</span> 按钮同步到左侧结果栏</li>
</ol>
</div>
</template>
@@ -454,16 +439,9 @@ function minusStartTime(val: Sentence) {
/>
<div class="justify-between items-center flex">
<div class="flex gap-space items-center w-50">
<BaseButton @click="startNetworkTranslate" :loading="progress !== 0 && progress !== 100"
>翻译
</BaseButton>
<BaseButton @click="startNetworkTranslate" :loading="progress !== 0 && progress !== 100">翻译 </BaseButton>
<Select v-model="networkTranslateEngine">
<Option
v-for="item in TranslateEngineOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<Option v-for="item in TranslateEngineOptions" :key="item.value" :label="item.label" :value="item.value" />
</Select>
{{ progress }}%
</div>
@@ -474,9 +452,7 @@ function minusStartTime(val: Sentence) {
<div>
<div class="mb-2">使用方法</div>
<ol class="py-0 pl-5 my-0 text-base color-black/60">
<li>
复制译文如果没有请点击 <span class="color-red font-bold">翻译</span> 按钮
</li>
<li>复制译文如果没有请点击 <span class="color-red font-bold">翻译</span> 按钮</li>
<li>
点击 <span class="color-red font-bold">分句</span> 按钮进行自动分句<span
class="color-red font-bold"
@@ -521,7 +497,7 @@ function minusStartTime(val: Sentence) {
</BaseIcon>
</div>
</div>
<div class="article-translate">
<div class="article-translate" ref="resultRef">
<div class="section rounded-md" v-for="(item, indexI) in editArticle.sections">
<div class="section-title text-lg font-bold">{{ indexI + 1 }}</div>
<div class="sentence" v-for="(sentence, indexJ) in item">
@@ -546,23 +522,17 @@ function minusStartTime(val: Sentence) {
<div class="flex gap-1">
<BaseIcon
@click="setStartTime(sentence, indexI, indexJ)"
:title="
indexI === 0 && indexJ === 0 ? '设置开始时间' : '使用前一句的结束时间'
"
:title="indexI === 0 && indexJ === 0 ? '设置开始时间' : '使用前一句的结束时间'"
>
<IconFluentMyLocation20Regular v-if="indexI === 0 && indexJ === 0" />
<IconFluentPaddingLeft20Regular v-else />
</BaseIcon>
<BaseIcon @click="minusStartTime(sentence)" title="减 0.3 秒">
-.3s
</BaseIcon>
<BaseIcon @click="minusStartTime(sentence)" title="减 0.3 秒"> -.3s </BaseIcon>
</div>
</div>
<div>-</div>
<div class="flex flex-col items-center justify-center">
<div v-if="sentence.audioPosition?.[1] !== -1">
{{ sentence.audioPosition?.[1] ?? 0 }}s
</div>
<div v-if="sentence.audioPosition?.[1] !== -1">{{ sentence.audioPosition?.[1] ?? 0 }}s</div>
<div v-else>结束</div>
<BaseIcon @click="setEndTime(sentence, indexI, indexJ)" title="设置结束时间">
<IconFluentMyLocation20Regular />
@@ -571,9 +541,7 @@ function minusStartTime(val: Sentence) {
</div>
<div class="flex flex-col">
<BaseIcon
:icon="
sentence.audioPosition?.length ? 'basil:edit-outline' : 'basil:add-outline'
"
:icon="sentence.audioPosition?.length ? 'basil:edit-outline' : 'basil:add-outline'"
title="编辑音频对齐"
@click="handleShowEditAudioDialog(sentence, indexI, indexJ)"
>
@@ -609,9 +577,7 @@ function minusStartTime(val: Sentence) {
</div>
<div>
<BaseButton @click="save('save')">保存</BaseButton>
<BaseButton v-if="type === 'batch'" @click="save('saveAndNext')"
>保存并添加下一篇</BaseButton
>
<BaseButton v-if="type === 'batch'" @click="save('saveAndNext')">保存并添加下一篇</BaseButton>
</div>
</div>
</template>
@@ -630,23 +596,13 @@ function minusStartTime(val: Sentence) {
<span class="color-red">记录</span> 按钮当播放到句子结束时点击结束时间的
<span class="color-red">记录</span> 按钮最后再试听是否正确
</div>
<ArticleAudio
ref="sentenceAudioRef"
:article="editArticle"
:autoplay="false"
class="w-full"
/>
<div
class="flex items-center gap-2 justify-between mb-2"
v-if="editSentence.audioPosition?.length"
>
<ArticleAudio ref="sentenceAudioRef" :article="editArticle" :autoplay="false" class="w-full" />
<div class="flex items-center gap-2 justify-between mb-2" v-if="editSentence.audioPosition?.length">
<div>{{ editSentence.text }}</div>
<div class="flex items-center gap-2 shrink-0">
<div>
<span>{{ editSentence.audioPosition?.[0] }}s</span>
<span v-if="editSentence.audioPosition?.[1] !== -1">
- {{ editSentence.audioPosition?.[1] }}s</span
>
<span v-if="editSentence.audioPosition?.[1] !== -1"> - {{ editSentence.audioPosition?.[1] }}s</span>
<span v-else> - 结束</span>
</div>
<BaseIcon title="播放" @click="playSentenceAudio(editSentence, sentenceAudioRef)">
@@ -674,21 +630,13 @@ function minusStartTime(val: Sentence) {
<IconFluentPaddingLeft20Regular />
</BaseIcon>
<BaseIcon
@click="
editSentence.audioPosition[0] = Number(
(editSentence.audioPosition[0] - 0.3).toFixed(2)
)
"
@click="editSentence.audioPosition[0] = Number((editSentence.audioPosition[0] - 0.3).toFixed(2))"
title="减少 0.3 秒"
>
-.3s
</BaseIcon>
<BaseIcon
@click="
editSentence.audioPosition[0] = Number(
(editSentence.audioPosition[0] + 0.3).toFixed(2)
)
"
@click="editSentence.audioPosition[0] = Number((editSentence.audioPosition[0] + 0.3).toFixed(2))"
title="增加 0.3 秒"
>
+.3s
@@ -703,9 +651,7 @@ function minusStartTime(val: Sentence) {
<div class="flex items-center gap-2">
<InputNumber v-model="editSentence.audioPosition[1]" :precision="2" :step="0.1" />
<span></span>
<BaseButton size="small" @click="editSentence.audioPosition[1] = -1"
>结束</BaseButton
>
<BaseButton size="small" @click="editSentence.audioPosition[1] = -1">结束</BaseButton>
</div>
<BaseButton @click="recordEnd">记录</BaseButton>
</div>
@@ -714,12 +660,7 @@ function minusStartTime(val: Sentence) {
</div>
</Dialog>
<Dialog
title="音频管理"
v-model="showAudioDialog"
:footer="false"
@close="showAudioDialog = false"
>
<Dialog title="音频管理" v-model="showAudioDialog" :footer="false" @close="showAudioDialog = false">
<div class="p-4 pt-0 color-main w-150 flex flex-col gap-2">
<div class="">
1上传的文件保存在本地电脑上更换电脑数据将丢失请及时备份数据
@@ -748,13 +689,7 @@ function minusStartTime(val: Sentence) {
</div>
</Dialog>
<Dialog
title="人名管理"
v-model="showNameDialog"
:footer="true"
@close="showNameDialog = false"
@ok="saveNameList"
>
<Dialog title="人名管理" v-model="showNameDialog" :footer="true" @close="showNameDialog = false" @ok="saveNameList">
<div class="p-4 pt-0 color-main w-150 flex flex-col gap-3">
<div class="flex justify-between items-center">
<div class="text-base">配置需要忽略的人名练习时自动忽略这些名称(可选默认开启)</div>

View File

@@ -14,6 +14,7 @@ import Form from "@/components/base/form/Form.vue";
import FormItem from "@/components/base/form/FormItem.vue";
import { addDict } from "@/apis";
import { AppEnv } from "@/config/env.ts";
import { nanoid } from 'nanoid'
const props = defineProps<{
isAdd: boolean,
@@ -80,7 +81,7 @@ async function onSubmit() {
if (!data.custom && ![DictId.wordKnown, DictId.wordWrong, DictId.wordCollect, DictId.articleCollect].includes(data.en_name || data.id)) {
data.custom = true
if (!data.id.includes('_custom')) {
data.id += '_custom'
data.id +='_custom_' + nanoid(6)
}
}
runtimeStore.editDict = data

View File

@@ -87,7 +87,7 @@ function syncDictInMyStudyList(study = false) {
) {
temp.custom = true
if (!temp.id.includes('_custom')) {
temp.id += '_custom'
temp.id += '_custom_' + nanoid(6)
}
}
temp.length = temp.words.length

View File

@@ -66,7 +66,7 @@ export interface Sentence {
}
export interface Article {
id?: number
id?: number|string
title: string
titleTranslate: string
text: string