+
+
{{ index + 1 }}.
{{ item.word }}
{{ item.phonetic0 }}
@@ -72,5 +73,10 @@ defineExpose({scrollToBottom, scrollToItem})
diff --git a/src/pages/setting/Setting.vue b/src/pages/setting/Setting.vue
index 3ffc53ae..f1af2864 100644
--- a/src/pages/setting/Setting.vue
+++ b/src/pages/setting/Setting.vue
@@ -152,7 +152,9 @@ function getShortcutKeyName(key: string): string {
'ToggleDictation': '切换默写模式',
'ToggleTheme': '切换主题',
'ToggleConciseMode': '切换简洁模式',
- 'TogglePanel': '切换面板'
+ 'TogglePanel': '切换面板',
+ 'RandomWrite': '随机默写',
+ 'NextRandomWrite': '继续随机默写'
}
return shortcutKeyNameMap[key] || key
diff --git a/src/pages/word/PracticeWords.vue b/src/pages/word/PracticeWords.vue
index 0aacca14..1630202c 100644
--- a/src/pages/word/PracticeWords.vue
+++ b/src/pages/word/PracticeWords.vue
@@ -57,6 +57,8 @@ let data = $ref
({
wrongWords: [],
})
+let isRandomWrite = false;
+
async function loadDict() {
// console.log('load好了开始加载')
let dict = getDefaultDict()
@@ -229,7 +231,8 @@ function next(isTyping: boolean = true) {
//开始默写新词
if (statStore.step === 0) {
- if (settingStore.wordPracticeMode === 1) {
+ if (settingStore.wordPracticeMode === 1 || isRandomWrite) {
+ isRandomWrite = false
console.log('自由模式,全完学完了')
showStatDialog = true
localStorage.removeItem(PracticeSaveWordKey.key)
@@ -380,9 +383,24 @@ function continueStudy() {
initData(getCurrentStudyWord())
}
+function randomWrite() {
+ console.log('随机默写')
+ data.words = shuffle(data.words);
+ data.index = 0
+ settingStore.dictation = true
+ isRandomWrite = true
+}
+function nextRandomWrite() {
+ console.log('继续随机默写')
+ initData(getCurrentStudyWord())
+ randomWrite();
+ showStatDialog = false
+}
+
useEvents([
[EventKey.repeatStudy, repeat],
[EventKey.continueStudy, continueStudy],
+ [EventKey.randomWrite, nextRandomWrite],
[EventKey.changeDict, () => {
initData(getCurrentStudyWord())
}],
@@ -401,6 +419,8 @@ useEvents([
[ShortcutKey.ToggleTheme, toggleTheme],
[ShortcutKey.ToggleConciseMode, toggleConciseMode],
[ShortcutKey.TogglePanel, togglePanel],
+ [ShortcutKey.RandomWrite, randomWrite],
+ [ShortcutKey.NextRandomWrite, nextRandomWrite],
])
@@ -453,6 +473,11 @@ useEvents([
:title="`下一组(${settingStore.shortcutKeyMap[ShortcutKey.NextChapter]})`">
+
+
+
diff --git a/src/pages/word/Statistics.vue b/src/pages/word/Statistics.vue
index ca090289..f6a5cafe 100644
--- a/src/pages/word/Statistics.vue
+++ b/src/pages/word/Statistics.vue
@@ -168,6 +168,11 @@ function options(emitType: string) {
@click="options(EventKey.continueStudy)">
{{ dictIsEnd ? '重新练习' : '再来一组' }}
+
+ 继续默写
+
返回主页
diff --git a/src/types/types.ts b/src/types/types.ts
index 0f2cca47..68b2bd7e 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -115,7 +115,9 @@ export enum ShortcutKey {
ToggleDictation = 'ToggleDictation',
ToggleTheme = 'ToggleTheme',
ToggleConciseMode = 'ToggleConciseMode',
- TogglePanel = 'TogglePanel'
+ TogglePanel = 'TogglePanel',
+ RandomWrite = 'RandomWrite',
+ NextRandomWrite = 'NextRandomWrite'
}
export const DefaultShortcutKeyMap = {
@@ -135,6 +137,8 @@ export const DefaultShortcutKeyMap = {
[ShortcutKey.ToggleTheme]: 'Ctrl+Q',
[ShortcutKey.ToggleConciseMode]: 'Ctrl+M',
[ShortcutKey.TogglePanel]: 'Ctrl+L',
+ [ShortcutKey.RandomWrite]: 'Ctrl+R',
+ [ShortcutKey.NextRandomWrite]: 'Ctrl+Shift+R',
}
export enum TranslateEngine {
diff --git a/src/utils/eventBus.ts b/src/utils/eventBus.ts
index 4ce756ce..6fb47c48 100644
--- a/src/utils/eventBus.ts
+++ b/src/utils/eventBus.ts
@@ -17,6 +17,7 @@ export const EventKey = {
editDict: 'editDict',
openMyDictDialog: 'openMyDictDialog',
stateInitEnd: 'stateInitEnd',
+ randomWrite: 'randomWrite',
}
export function useEvent(key: string, func: any) {
From 72377100db90f53708ba71cc3b6f25e1c5a4719e Mon Sep 17 00:00:00 2001
From: hamburger <346002234@qq.com>
Date: Wed, 8 Oct 2025 11:25:29 +0800
Subject: [PATCH 2/3] =?UTF-8?q?3=20=E6=96=87=E7=AB=A0=E6=92=AD=E6=94=BE?=
=?UTF-8?q?=E5=AE=8C=E5=90=8E=E8=87=AA=E5=8A=A8=E6=92=AD=E6=94=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/base/Audio.vue | 5 ++
src/pages/article/BookDetail.vue | 16 +++++-
src/pages/article/PracticeArticles.vue | 15 +++++-
src/pages/article/components/ArticleAudio.vue | 51 ++++++++++++++++++-
4 files changed, 84 insertions(+), 3 deletions(-)
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({
+ :src="props.article.audioSrc"
+ @ended="handleAudioEnded"/>
From 281664c7eae2246d833bc38483d028756847be2b Mon Sep 17 00:00:00 2001
From: hamburger <346002234@qq.com>
Date: Wed, 8 Oct 2025 11:42:46 +0800
Subject: [PATCH 3/3] 1
---
package.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/package.json b/package.json
index 306fd8a8..4cada8f7 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,6 @@
"i18n:write": "gulp i18nwrite",
"deploy-oss": "node scripts/deploy-oss.js"
},
- "type": "module",
"dependencies": {
"@imengyu/vue3-context-menu": "^1.5.1",
"axios": "^1.10.0",