Small optimization

This commit is contained in:
zyronon
2024-01-03 10:12:41 +08:00
parent 4464dde128
commit 95a63465c5
5 changed files with 201 additions and 150 deletions

View File

@@ -84,7 +84,7 @@ onMounted(() => {
}
}
drawMoon()
// drawMoon()
})
</script>

View File

@@ -1,20 +1,20 @@
<script setup lang="ts">
import {Icon} from '@iconify/vue';
import {ref, watch} from "vue";
import {useSettingStore} from "@/stores/setting.ts";
import {getAudioFileUrl, useChangeAllSound, usePlayAudio, useWatchAllSound} from "@/hooks/sound.ts";
import {getShortcutKey, useDisableEventListener, useEventListener} from "@/hooks/event.ts";
import {$computed, $ref} from "vue/macros";
import {cloneDeep} from "lodash-es";
import {DefaultShortcutKeyMap, Dict, DictType, ShortcutKey} from "@/types.ts";
import { Icon } from '@iconify/vue';
import { ref, watch } from "vue";
import { useSettingStore } from "@/stores/setting.ts";
import { getAudioFileUrl, useChangeAllSound, usePlayAudio, useWatchAllSound } from "@/hooks/sound.ts";
import { getShortcutKey, useDisableEventListener, useEventListener } from "@/hooks/event.ts";
import { $computed, $ref } from "vue/macros";
import { cloneDeep } from "lodash-es";
import { DefaultShortcutKeyMap, Dict, DictType, ShortcutKey } from "@/types.ts";
import BaseButton from "@/components/BaseButton.vue";
import {APP_NAME, EXPORT_DATA_KEY, SAVE_DICT_KEY, SAVE_SETTING_KEY, SoundFileOptions} from "@/utils/const.ts";
import { APP_NAME, EXPORT_DATA_KEY, SAVE_DICT_KEY, SAVE_SETTING_KEY, SoundFileOptions } from "@/utils/const.ts";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {BaseState, useBaseStore} from "@/stores/base.ts";
import { BaseState, useBaseStore } from "@/stores/base.ts";
import * as copy from "copy-to-clipboard";
import {saveAs} from "file-saver";
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, shakeCommonDict} from "@/utils";
import {dayjs} from "element-plus";
import { saveAs } from "file-saver";
import { checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, shakeCommonDict } from "@/utils";
import { dayjs } from "element-plus";
const emit = defineEmits<{
@@ -344,7 +344,20 @@ function importData(e) {
<label class="item-title">其他设置</label>
</div>
<div class="row">
<label class="sub-title">切换下一个单词时间</label>
<label class="sub-title">是否自动切换下一个单词</label>
<div class="wrapper">
<el-switch v-model="settingStore.autoNext"
inline-prompt
active-text="开"
inactive-text="关"
/>
</div>
</div>
<div class="desc">
关闭后,当完成单词输入时,需要再次按下空格键切换下一个
</div>
<div class="row">
<label class="sub-title">自动切换下一个单词延迟</label>
<div class="wrapper">
<el-input-number v-model="settingStore.waitTimeForChangeWord"
:min="0"
@@ -353,6 +366,20 @@ function importData(e) {
<span>毫秒</span>
</div>
</div>
<div class="row">
<label class="sub-title">默写时是否显示单词长度</label>
<div class="wrapper">
<el-switch v-model="settingStore.dictationShowWordLength"
inline-prompt
active-text="开"
inactive-text="关"
/>
</div>
</div>
<div class="desc">
默写时用下划线 _ 来显示每个字符。关闭后,用空格代替,用户将无法判断单词长度
</div>
</div>
<div class="body" v-if="tabIndex === 2">
<div class="row">

View File

@@ -1,14 +1,14 @@
<script setup lang="ts">
import {DefaultWord, ShortcutKey, Word} from "@/types.ts";
import { DefaultWord, ShortcutKey, Word } from "@/types.ts";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {$computed, $ref} from "vue/macros";
import {useBaseStore} from "@/stores/base.ts";
import {usePracticeStore} from "@/stores/practice.ts";
import {useSettingStore} from "@/stores/setting.ts";
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio, useTTsPlayAudio} from "@/hooks/sound.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import {cloneDeep} from "lodash-es";
import {onUnmounted, watch, onMounted} from "vue";
import { $computed, $ref } from "vue/macros";
import { useBaseStore } from "@/stores/base.ts";
import { usePracticeStore } from "@/stores/practice.ts";
import { useSettingStore } from "@/stores/setting.ts";
import { usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio, useTTsPlayAudio } from "@/hooks/sound.ts";
import { emitter, EventKey } from "@/utils/eventBus.ts";
import { cloneDeep } from "lodash-es";
import { onUnmounted, watch, onMounted } from "vue";
import Tooltip from "@/components/Tooltip.vue";
interface IProps {
@@ -27,6 +27,7 @@ const emit = defineEmits<{
let input = $ref('')
let wrong = $ref('')
let showFullWord = $ref(false)
let waitNext = $ref(false)
//输入锁定因为跳转到下一个单词有延时如果重复在延时期间内重复输入导致会跳转N次
let inputLock = false
let wordRepeatCount = 0
@@ -79,6 +80,13 @@ function repeat() {
}
async function onTyping(e: KeyboardEvent) {
if (waitNext) {
if (e.code === 'Space') {
emit('next')
waitNext = false
}
return
}
if (inputLock) return
inputLock = true
let letter = e.key
@@ -110,13 +118,23 @@ async function onTyping(e: KeyboardEvent) {
playCorrect()
if (settingStore.repeatCount == 100) {
if (settingStore.repeatCustomCount <= wordRepeatCount + 1) {
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
if (settingStore.autoNext) {
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
} else {
waitNext = true
inputLock = false
}
} else {
repeat()
}
} else {
if (settingStore.repeatCount <= wordRepeatCount + 1) {
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
if (settingStore.autoNext) {
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
} else {
waitNext = true
inputLock = false
}
} else {
repeat()
}
@@ -139,6 +157,8 @@ function del() {
function showWord() {
if (settingStore.allowWordTip) {
showFullWord = true
//如果默写情况下,看了提示也视为输入错误
emit('wrong')
}
}
@@ -163,17 +183,17 @@ defineExpose({del, showWord, hideWord, play})
>
<div class="translate-item" v-for="(v,i) in word.trans">
<span>{{ v }}</span>
<!-- <div class="volumeIcon">-->
<!-- <Tooltip-->
<!-- v-if="i === word.trans.length - 1"-->
<!-- :title="`发音(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.PlayTranslatePronunciation]})`"-->
<!-- >-->
<!-- <VolumeIcon-->
<!-- ref="volumeTranslateIconRef"-->
<!-- :simple="true"-->
<!-- :cb="()=>ttsPlayAudio(word.trans.join(';'))"/>-->
<!-- </Tooltip>-->
<!-- </div>-->
<!-- <div class="volumeIcon">-->
<!-- <Tooltip-->
<!-- v-if="i === word.trans.length - 1"-->
<!-- :title="`发音(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.PlayTranslatePronunciation]})`"-->
<!-- >-->
<!-- <VolumeIcon-->
<!-- ref="volumeTranslateIconRef"-->
<!-- :simple="true"-->
<!-- :cb="()=>ttsPlayAudio(word.trans.join(';'))"/>-->
<!-- </Tooltip>-->
<!-- </div>-->
</div>
</div>
<div class="word-wrapper">
@@ -185,10 +205,10 @@ defineExpose({del, showWord, hideWord, play})
<span class="wrong" v-if="wrong">{{ wrong }}</span>
<template v-if="settingStore.dictation">
<span class="letter" v-if="!showFullWord"
@mouseenter="settingStore.allowWordTip && (showFullWord = true)">{{
displayWord.split('').map(() => '_').join('')
@mouseenter="showWord">{{
displayWord.split('').map(() => settingStore.dictationShowWordLength ? '_' : '&nbsp;').join('')
}}</span>
<span class="letter" v-else @mouseleave="showFullWord = false">{{ displayWord }}</span>
<span class="letter" v-else @mouseleave="hideWord">{{ displayWord }}</span>
</template>
<span class="letter" v-else>{{ displayWord }}</span>
</div>
@@ -198,7 +218,7 @@ defineExpose({del, showWord, hideWord, play})
<VolumeIcon ref="volumeIconRef" :simple="true" :cb="() => playWordAudio(word.name)"/>
</Tooltip>
</div>
<div class="phonetic" v-if="settingStore.wordSoundType === 'us' && word.usphone">[{{ word.usphone}}]</div>
<div class="phonetic" v-if="settingStore.wordSoundType === 'us' && word.usphone">[{{ word.usphone }}]</div>
<div class="phonetic" v-if="settingStore.wordSoundType === 'uk' && word.ukphone">[{{ word.ukphone }}]</div>
</div>
</template>

View File

@@ -1,21 +1,21 @@
<script setup lang="ts">
import {onMounted, onUnmounted, watch} from "vue"
import {$computed, $ref} from "vue/macros"
import {useBaseStore} from "@/stores/base.ts"
import {DefaultDisplayStatistics, DictType, ShortcutKey, Sort, Word} from "../../../types.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts"
import {cloneDeep, reverse, shuffle} from "lodash-es"
import {usePracticeStore} from "@/stores/practice.ts"
import {useSettingStore} from "@/stores/setting.ts";
import {useOnKeyboardEventListener, useWindowClick} from "@/hooks/event.ts";
import {Icon} from "@iconify/vue";
import { onMounted, onUnmounted, watch } from "vue"
import { $computed, $ref } from "vue/macros"
import { useBaseStore } from "@/stores/base.ts"
import { DefaultDisplayStatistics, DictType, ShortcutKey, Sort, Word } from "../../../types.ts";
import { emitter, EventKey } from "@/utils/eventBus.ts"
import { cloneDeep, reverse, shuffle } from "lodash-es"
import { usePracticeStore } from "@/stores/practice.ts"
import { useSettingStore } from "@/stores/setting.ts";
import { useOnKeyboardEventListener, useWindowClick } from "@/hooks/event.ts";
import { Icon } from "@iconify/vue";
import Tooltip from "@/components/Tooltip.vue";
import Options from "@/pages/practice/Options.vue";
import Typing from "@/pages/practice/practice-word/Typing.vue";
import Panel from "@/pages/practice/Panel.vue";
import IconWrapper from "@/components/IconWrapper.vue";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {syncMyDictList, useWordOptions} from "@/hooks/dict.ts";
import { useRuntimeStore } from "@/stores/runtime.ts";
import { syncMyDictList, useWordOptions } from "@/hooks/dict.ts";
import BaseIcon from "@/components/BaseIcon.vue";
import WordList from "@/components/list/WordList.vue";
import Empty from "@/components/Empty.vue";
@@ -99,7 +99,6 @@ const nextWord: Word = $computed(() => {
function next(isTyping: boolean = true) {
if (data.index === data.words.length - 1) {
//复制当前错词,因为第一遍错词是最多的,后续的练习都是从错词中练习
if (stat.total === -1) {
let now = Date.now()
@@ -140,8 +139,7 @@ function next(isTyping: boolean = true) {
data.index++
isTyping && practiceStore.inputWordNumber++
console.log('这个词完了')
if ([DictType.word].includes(store.currentDict.type)
&& store.skipWordNames.includes(word.name.toLowerCase())) {
if (store.skipWordNames.includes(word.name.toLowerCase())) {
next()
}
}

View File

@@ -1,108 +1,114 @@
import {defineStore} from "pinia"
import {cloneDeep, merge} from "lodash-es";
import {DefaultShortcutKeyMap} from "@/types.ts";
import {SAVE_SETTING_KEY} from "@/utils/const.ts";
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting} from "@/utils";
import { defineStore } from "pinia"
import { cloneDeep, merge } from "lodash-es";
import { DefaultShortcutKeyMap } from "@/types.ts";
import { SAVE_SETTING_KEY } from "@/utils/const.ts";
import { checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting } from "@/utils";
export interface SettingState {
showToolbar: boolean,
show: boolean,
showToolbar: boolean,
show: boolean,
allSound: boolean,
wordSound: boolean,
wordSoundVolume: number,
wordSoundSpeed: number,
wordSoundType: string,
keyboardSound: boolean,
keyboardSoundVolume: number,
keyboardSoundFile: string,
translateSound: boolean,
translateSoundVolume: number,
effectSound: boolean,
effectSoundVolume: number,
repeatCount: number,
repeatCustomCount?: number,
dictation: boolean,
translate: boolean,
showNearWord: boolean
ignoreCase: boolean
allowWordTip: boolean
waitTimeForChangeWord: number
fontSize: {
articleForeignFontSize: number,
articleTranslateFontSize: number,
wordForeignFontSize: number,
wordTranslateFontSize: number,
},
showPanel: boolean,
theme: string,
collapse: boolean,
chapterWordNumber: number,
shortcutKeyMap: Record<string, string>,
first: boolean
load: boolean
allSound: boolean,
wordSound: boolean,
wordSoundVolume: number,
wordSoundSpeed: number,
wordSoundType: string,
keyboardSound: boolean,
keyboardSoundVolume: number,
keyboardSoundFile: string,
translateSound: boolean,
translateSoundVolume: number,
effectSound: boolean,
effectSoundVolume: number,
repeatCount: number,
repeatCustomCount?: number,
dictation: boolean,
translate: boolean,
showNearWord: boolean
ignoreCase: boolean
allowWordTip: boolean
waitTimeForChangeWord: number
autoNext: boolean
dictationShowWordLength: boolean//默写时显示单词长度,即用下划线 _ 来显示每个字符
fontSize: {
articleForeignFontSize: number,
articleTranslateFontSize: number,
wordForeignFontSize: number,
wordTranslateFontSize: number,
},
showPanel: boolean,
theme: string,
collapse: boolean,
chapterWordNumber: number,
shortcutKeyMap: Record<string, string>,
first: boolean
load: boolean
}
export const DefaultSettingState = (): SettingState => ({
showToolbar: true,
show: false,
showPanel: true,
showToolbar: true,
show: false,
showPanel: true,
allSound: true,
wordSound: true,
wordSoundVolume: 100,
wordSoundSpeed: 1,
wordSoundType: 'us',
keyboardSound: true,
keyboardSoundVolume: 100,
keyboardSoundFile: '机械键盘2',
translateSound: true,
translateSoundVolume: 100,
effectSound: true,
effectSoundVolume: 100,
repeatCount: 1,
repeatCustomCount: null,
dictation: false,
translate: true,
allSound: true,
wordSound: true,
wordSoundVolume: 100,
wordSoundSpeed: 1,
wordSoundType: 'us',
keyboardSound: true,
keyboardSoundVolume: 100,
keyboardSoundFile: '机械键盘2',
translateSound: true,
translateSoundVolume: 100,
effectSound: true,
effectSoundVolume: 100,
repeatCount: 1,
repeatCustomCount: null,
dictation: false,
translate: true,
showNearWord: true,
ignoreCase: true,
allowWordTip: true,
fontSize: {
articleForeignFontSize: 48,
articleTranslateFontSize: 20,
wordForeignFontSize: 48,
wordTranslateFontSize: 20,
},
waitTimeForChangeWord: 300,
theme: 'auto',
collapse: false,
chapterWordNumber: DefaultChapterWordNumber,
shortcutKeyMap: cloneDeep(DefaultShortcutKeyMap),
first: true,
load: false
showNearWord: true,
ignoreCase: true,
allowWordTip: true,
fontSize: {
articleForeignFontSize: 48,
articleTranslateFontSize: 20,
wordForeignFontSize: 48,
wordTranslateFontSize: 20,
},
waitTimeForChangeWord: 300,
autoNext: true,
dictationShowWordLength: true,
theme: 'auto',
collapse: false,
chapterWordNumber: DefaultChapterWordNumber,
shortcutKeyMap: cloneDeep(DefaultShortcutKeyMap),
first: true,
load: false
})
export const DefaultChapterWordNumber = 30
export const useSettingStore = defineStore('setting', {
state: (): SettingState => {
return DefaultSettingState()
state: (): SettingState => {
return DefaultSettingState()
},
actions: {
setState(obj: any) {
//这样不会丢失watch的值的引用
merge(this, obj)
},
actions: {
setState(obj: any) {
//这样不会丢失watch的值的引用
merge(this, obj)
},
init() {
return new Promise(resolve => {
let configStr = localStorage.getItem(SAVE_SETTING_KEY.key)
if (!configStr) configStr = localStorage.getItem(SAVE_SETTING_KEY.oldKey)
let data = checkAndUpgradeSaveSetting(configStr)
this.setState(data)
localStorage.setItem(SAVE_SETTING_KEY.key, JSON.stringify({val: this.$state, version: SAVE_SETTING_KEY.version}))
this.load = true
resolve(true)
})
}
init() {
return new Promise(resolve => {
let configStr = localStorage.getItem(SAVE_SETTING_KEY.key)
if (!configStr) configStr = localStorage.getItem(SAVE_SETTING_KEY.oldKey)
let data = checkAndUpgradeSaveSetting(configStr)
this.setState(data)
localStorage.setItem(SAVE_SETTING_KEY.key, JSON.stringify({
val: this.$state,
version: SAVE_SETTING_KEY.version
}))
this.load = true
resolve(true)
})
}
}
})