diff --git a/src/components/base/Audio.vue b/src/components/base/Audio.vue index 25bd3726..5711be6a 100644 --- a/src/components/base/Audio.vue +++ b/src/components/base/Audio.vue @@ -119,9 +119,14 @@ const handlePause = () => { isPlaying.value = false; }; +const emit = defineEmits<{ + ended: [] +}>(); + const handleEnded = () => { isPlaying.value = false; currentTime.value = 0; + emit('ended'); }; const handleError = () => { diff --git a/src/pages/article/BookDetail.vue b/src/pages/article/BookDetail.vue index ff8ca796..1f38c074 100644 --- a/src/pages/article/BookDetail.vue +++ b/src/pages/article/BookDetail.vue @@ -33,6 +33,16 @@ let studyLoading = $ref(false) let selectArticle: Article = $ref(getDefaultArticle()) +// 计算当前选中文章的索引 +const currentArticleIndex = computed(() => { + return runtimeStore.editDict.articles.findIndex(article => article.id === selectArticle.id) +}) + +// 处理播放下一个音频 +const handlePlayNext = (nextArticle: Article) => { + selectArticle = nextArticle +} + function handleCheckedChange(val) { selectArticle = val.item } @@ -191,7 +201,11 @@ const totalSpend = $computed(() => {
- +
{{ selectArticle.title }}
diff --git a/src/pages/article/PracticeArticles.vue b/src/pages/article/PracticeArticles.vue index 23e1bf95..9d42a1f1 100644 --- a/src/pages/article/PracticeArticles.vue +++ b/src/pages/article/PracticeArticles.vue @@ -328,6 +328,14 @@ function changeArticle(val: ArticleItem) { } } +const handlePlayNext = (nextArticle: Article) => { + let rIndex = articleData.list.findIndex(v => v.id === nextArticle.id) + if (rIndex > -1) { + store.sbook.lastLearnIndex = rIndex + getCurrentPractice() + } +} + const { isArticleCollect, toggleArticleCollect @@ -489,7 +497,12 @@ provide('currentPractice', currentPractice)
单词总数
- +
diff --git a/src/pages/article/components/ArticleAudio.vue b/src/pages/article/components/ArticleAudio.vue index fe3c9e24..5995ee6e 100644 --- a/src/pages/article/components/ArticleAudio.vue +++ b/src/pages/article/components/ArticleAudio.vue @@ -7,10 +7,45 @@ import Audio from "@/components/base/Audio.vue"; const props = defineProps<{ article: Article + articleList?: Article[] + currentIndex?: number }>() let file = $ref(null) let instance = $ref<{ audioRef: HTMLAudioElement }>({audioRef: null}) +let shouldAutoPlay = $ref(false) // 标记是否应该自动播放 + +const emit = defineEmits<{ + playNext: [nextArticle: Article] +}>() + +// 处理音频播放结束,自动播放下一个 +const handleAudioEnded = () => { + if (props.articleList && props.currentIndex !== undefined) { + const nextIndex = props.currentIndex + 1 + if (nextIndex < props.articleList.length) { + const nextArticle = props.articleList[nextIndex] + if (nextArticle.audioSrc || nextArticle.audioFileId) { + shouldAutoPlay = true // 设置自动播放标记 + emit('playNext', nextArticle) + } + } + } +} + +// 当音频源改变时,如果需要自动播放则开始播放 +const startAutoPlay = async () => { + if (shouldAutoPlay && instance?.audioRef) { + shouldAutoPlay = false // 重置标记 + try { + // 等待一小段时间确保音频元素已经准备好 + await new Promise(resolve => setTimeout(resolve, 100)) + await instance.audioRef.play() + } catch (error) { + console.error('自动播放失败:', error) + } + } +} watch(() => props.article.audioFileId, async () => { if (!props.article.audioSrc && props.article.audioFileId) { @@ -19,6 +54,9 @@ watch(() => props.article.audioFileId, async () => { let rItem = list.find((file) => file.id === props.article.audioFileId) if (rItem) { file = URL.createObjectURL(rItem.file) + // 当文件加载完成后尝试自动播放 + await new Promise(resolve => setTimeout(resolve, 50)) + startAutoPlay() } } }else { @@ -26,6 +64,15 @@ watch(() => props.article.audioFileId, async () => { } }, {immediate: true}) +// 监听音频源变化,触发自动播放 +watch(() => props.article.audioSrc, async (newSrc) => { + if (newSrc) { + // 当音频源改变后尝试自动播放 + await new Promise(resolve => setTimeout(resolve, 50)) + startAutoPlay() + } +}) + //转发一遍,这里Proxy的默认值不能为{},可能是vue做了什么 defineExpose(new Proxy({ currentTime: 0, @@ -57,8 +104,10 @@ defineExpose(new Proxy({