From 3b5d8d94ed5aac156cb47f3643fb1f7c22855501 Mon Sep 17 00:00:00 2001 From: zyronon Date: Sun, 14 Sep 2025 16:41:33 +0800 Subject: [PATCH] feat:improve the audio function of the article --- components.d.ts | 1 + public/dicts/en/article/NCE_2.json | 7 +- src/assets/css/style.scss | 6 +- src/hooks/article.ts | 2 +- src/pages/pc/article/BookDetail.vue | 8 +- src/pages/pc/article/StudyArticle.vue | 7 +- .../pc/article/components/ArticleAudio.vue | 62 +++++ src/pages/pc/article/components/Audio.vue | 38 --- .../pc/article/components/EditArticle.vue | 91 ++++--- src/pages/pc/components/base/Audio.vue | 243 +++++------------- 10 files changed, 189 insertions(+), 276 deletions(-) create mode 100644 src/pages/pc/article/components/ArticleAudio.vue delete mode 100644 src/pages/pc/article/components/Audio.vue diff --git a/components.d.ts b/components.d.ts index b8ab3fcc..40248dac 100644 --- a/components.d.ts +++ b/components.d.ts @@ -16,6 +16,7 @@ declare module 'vue' { IconBxVolume: typeof import('~icons/bx/volume')['default'] IconBxVolumeFull: typeof import('~icons/bx/volume-full')['default'] IconBxVolumeLow: typeof import('~icons/bx/volume-low')['default'] + IconBxVolumeMute: typeof import('~icons/bx/volume-mute')['default'] IconEosIconsLoading: typeof import('~icons/eos-icons/loading')['default'] IconFluentAdd16Filled: typeof import('~icons/fluent/add16-filled')['default'] IconFluentAdd16Regular: typeof import('~icons/fluent/add16-regular')['default'] diff --git a/public/dicts/en/article/NCE_2.json b/public/dicts/en/article/NCE_2.json index ba0df6b3..c2fe83ba 100644 --- a/public/dicts/en/article/NCE_2.json +++ b/public/dicts/en/article/NCE_2.json @@ -834,12 +834,13 @@ "id": "dWA516", "title": "Do you call that a hat?", "titleTranslate": "你把那个叫帽子吗?", - "text": "Do you call that a hat? I said to my wife. \nYou neednt be so rude about it, my wife answered as she looked at herself in the mirror. \nI sat down on one of those modern chairs with holes in it and waited. We had been in the hat shop for half an hour and my wife was still in front of the mirror. \nWe mustnt buy things we dont need, I remarked suddenly. I regretted saying it almost at once. \nYou neednt have said that, my wife answered. I neednt remind you of that terrible tie you bought yesterday. \nI find it beautiful, I said. A man can never have too many ties. \nAnd a woman cant have too many hats, she answered. \nTen minutes later we walked out of the shop together. My wife was wearing a hat that looked like a lighthouse!", - "textTranslate": "“你把那个叫帽子吗?”我对妻子说。 \n“你说话没必要这样不客气,”我的妻子边回答边照着镜子。 \n我坐在一个新式的满是网眼儿的椅子上,等待着。我们在这家帽店已经呆了半个小时了,而我的妻子仍在镜子面前。 \n“我们不应该买我们不需要的东西,”我突然发表意见说,但马上又后悔说了这话。 \n“你没必要这么说,”我妻子回答说,“我也不必提醒你昨天买的那条糟糕透了的领带。” \n“我觉得它好看,”我说,“男人有多少领带也不会嫌多。” \n“女人有多少帽子也不嫌多。”她回答。 \n10分钟以后,我们一道走出了商店。我妻子戴着一顶像灯塔一样的帽子。", + "text": "Do you call that a hat? I said to my wife. \nYou neednt be so rude about it, my wife answered as she looked at herself in the mirror. \nI sat down on one of those modern chairs with holes in it and waited. \nWe had been in the hat shop for half an hour and my wife was still in front of the mirror. \nWe mustnt buy things we dont need, I remarked suddenly. \nI regretted saying it almost at once. \nYou neednt have said that, my wife answered. \nI neednt remind you of that terrible tie you bought yesterday. \nI find it beautiful, I said. \nA man can never have too many ties. \nAnd a woman cant have too many hats, she answered. \nTen minutes later we walked out of the shop together. \nMy wife was wearing a hat that looked like a lighthouse!", + "textTranslate": "“你把那个叫帽子吗?”我对妻子说。 \n“你说话没必要这样不客气,”我的妻子边回答边照着镜子。 \n我坐在一个新式的满是网眼儿的椅子上,等待着。 \n我们在这家帽店已经呆了半个小时了,而我的妻子仍在镜子面前。 \n“我们不应该买我们不需要的东西,”我突然发表意见说, \n但马上又后悔说了这话。 \n“你没必要这么说,”我妻子回答说, \n“我也不必提醒你昨天买的那条糟糕透了的领带。” \n“我觉得它好看,”我说, \n“男人有多少领带也不会嫌多。” \n“女人有多少帽子也不嫌多。”她回答。 \n10分钟以后,我们一道走出了商店。 \n我妻子戴着一顶像灯塔一样的帽子。", "newWords": [], "textAllWords": [], "audioSrc": "", - "lrcPosition": [] + "lrcPosition": [], + "audioFileId": "TNJNgS" }, { "id": "XrDkqH", diff --git a/src/assets/css/style.scss b/src/assets/css/style.scss index 09ade5ee..7ee78e36 100644 --- a/src/assets/css/style.scss +++ b/src/assets/css/style.scss @@ -1,7 +1,8 @@ @use "anim" as *; :root { - --color-reverse: blank; + --color-reverse-white: white; + --color-reverse-black: black; --color-item-bg: rgb(228, 230, 232); --color-item-hover: white; //--color-item-active: rgb(75, 110, 175); @@ -76,6 +77,9 @@ } html.dark { + --color-reverse-white: black; + --color-reverse-black: white; + --color-primary: #0E1217; --color-second: rgb(30, 31, 34); --color-third: rgb(43, 45, 48); diff --git a/src/hooks/article.ts b/src/hooks/article.ts index 2bded9d2..c4984ace 100644 --- a/src/hooks/article.ts +++ b/src/hooks/article.ts @@ -555,7 +555,7 @@ export function usePlaySentenceAudio() { timer = setTimeout(() => { console.log('停') ref.pause() - }, (end - start) * 1000) + }, (end - start) / ref.playbackRate * 1000) } } else { playWordAudio(sentence.text) diff --git a/src/pages/pc/article/BookDetail.vue b/src/pages/pc/article/BookDetail.vue index b010be74..b6228e97 100644 --- a/src/pages/pc/article/BookDetail.vue +++ b/src/pages/pc/article/BookDetail.vue @@ -16,7 +16,7 @@ import BaseIcon from "@/components/BaseIcon.vue"; import {useArticleOptions} from "@/hooks/dict.ts"; import {getDefaultArticle, getDefaultDict} from "@/types/func.ts"; import Toast from "@/pages/pc/components/base/toast/Toast.ts"; -import Audio from "@/pages/pc/components/base/Audio.vue"; +import ArticleAudio from "@/pages/pc/article/components/ArticleAudio.vue"; const runtimeStore = useRuntimeStore() const base = useBaseStore() @@ -135,10 +135,8 @@ const {
-
- - - +
+
{{ selectArticle.title }}
diff --git a/src/pages/pc/article/StudyArticle.vue b/src/pages/pc/article/StudyArticle.vue index 127d9c67..f63489d2 100644 --- a/src/pages/pc/article/StudyArticle.vue +++ b/src/pages/pc/article/StudyArticle.vue @@ -24,6 +24,8 @@ import {useRoute, useRouter} from "vue-router"; import book_list from "@/assets/book-list.json"; import PracticeLayout from "@/pages/pc/components/PracticeLayout.vue"; import Switch from "@/pages/pc/components/base/Switch.vue"; +import Audio from "@/pages/pc/components/base/Audio.vue"; +import ArticleAudio from "@/pages/pc/article/components/ArticleAudio.vue"; const store = useBaseStore() const settingStore = useSettingStore() @@ -361,7 +363,7 @@ function play2(e) { color="#999"/>
-
+
{{ speedMinute }}分钟
@@ -385,8 +387,7 @@ function play2(e) {
单词总数
- +
diff --git a/src/pages/pc/article/components/ArticleAudio.vue b/src/pages/pc/article/components/ArticleAudio.vue new file mode 100644 index 00000000..e6658a25 --- /dev/null +++ b/src/pages/pc/article/components/ArticleAudio.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/pages/pc/article/components/Audio.vue b/src/pages/pc/article/components/Audio.vue deleted file mode 100644 index eac8ac07..00000000 --- a/src/pages/pc/article/components/Audio.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/pages/pc/article/components/EditArticle.vue b/src/pages/pc/article/components/EditArticle.vue index 1601ad41..d480c499 100644 --- a/src/pages/pc/article/components/EditArticle.vue +++ b/src/pages/pc/article/components/EditArticle.vue @@ -19,8 +19,7 @@ import InputNumber from "@/pages/pc/components/base/InputNumber.vue"; import {nanoid} from "nanoid"; import {update} from "idb-keyval"; import {LOCAL_FILE_KEY} from "@/utils/const.ts"; -// import Audio from "@/pages/pc/article/components/Audio.vue"; -import Audio from "@/pages/pc/components/base/Audio.vue"; +import ArticleAudio from "@/pages/pc/article/components/ArticleAudio.vue"; import BaseInput from "@/pages/pc/components/base/BaseInput.vue"; const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue')) @@ -160,7 +159,6 @@ function save(option: 'save' | 'saveAndNext') { emit(option as any, editArticle) return resolve(true) } - saveTemp() }) } @@ -237,15 +235,16 @@ let currentSentence = $ref({} as any) let editSentence = $ref({} as any) let preSentence = $ref({} as any) let showEditAudioDialog = $ref(false) -let sentenceAudioRef = $ref<{ el: HTMLAudioElement }>({el: null}) -let audioRef = $ref<{ el: HTMLAudioElement }>({el: null}) +let showAudioDialog = $ref(false) +let sentenceAudioRef = $ref() +let audioRef = $ref() function handleShowEditAudioDialog(val: Sentence, i: number, j: number) { showEditAudioDialog = true currentSentence = val editSentence = cloneDeep(val) preSentence = null - audioRef.el.pause() + audioRef.pause() if (j == 0) { if (i != 0) { preSentence = last(editArticle.sections[i - 1]) @@ -260,25 +259,25 @@ function handleShowEditAudioDialog(val: Sentence, i: number, j: number) { } } _nextTick(() => { - sentenceAudioRef.el.currentTime = editSentence.audioPosition[0] + sentenceAudioRef.currentTime = editSentence.audioPosition[0] }) } function recordStart() { - if (sentenceAudioRef.el.paused) { - sentenceAudioRef.el.play() + if (sentenceAudioRef.paused) { + sentenceAudioRef.play() } - editSentence.audioPosition[0] = Number(sentenceAudioRef.el.currentTime.toFixed(2)) + editSentence.audioPosition[0] = Number(sentenceAudioRef.currentTime.toFixed(2)) if (editSentence.audioPosition[0] > editSentence.audioPosition[1]) { editSentence.audioPosition[1] = editSentence.audioPosition[0] } } function recordEnd() { - if (!sentenceAudioRef.el.paused) { - sentenceAudioRef.el.pause() + if (!sentenceAudioRef.paused) { + sentenceAudioRef.pause() } - editSentence.audioPosition[1] = Number(sentenceAudioRef.el.currentTime.toFixed(2)) + editSentence.audioPosition[1] = Number(sentenceAudioRef.currentTime.toFixed(2)) } const {playSentenceAudio} = usePlaySentenceAudio() @@ -290,7 +289,7 @@ function saveLrcPosition() { } function jumpAudio(time: number) { - sentenceAudioRef.el.currentTime = time + sentenceAudioRef.currentTime = time } function setPreEndTimeToCurrentStartTime() { @@ -311,17 +310,13 @@ function setStartTime(val: Sentence, i: number, j: number) { if (preSentence) { val.audioPosition[0] = preSentence.audioPosition[1] } else { - val.audioPosition[0] = Number(Number(audioRef.el.currentTime).toFixed(2)) + val.audioPosition[0] = Number(Number(audioRef.currentTime).toFixed(2)) } if (val.audioPosition[0] > val.audioPosition[1]) { val.audioPosition[1] = val.audioPosition[0] } } -function uploadFileTrigger(id: string) { - (document.querySelector('#' + id) as HTMLDivElement)?.click() -} -