feat:change setting
This commit is contained in:
@@ -38,6 +38,8 @@
|
||||
document.write('<scr' + 'ipt>eruda.init();</scr' + 'ipt>');
|
||||
})();
|
||||
</script>
|
||||
<!-- 异常上报-->
|
||||
<script src="https://js.fundebug.cn/fundebug.revideo.0.7.1.min.js"></script>
|
||||
<script>
|
||||
if (!location.href.includes('localhost')
|
||||
&& !location.href.includes('192.168')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {onMounted, watch, watchEffect} from "vue"
|
||||
import {onMounted, watchEffect} from "vue"
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {PronunciationApi} from "@/types/types.ts";
|
||||
import {SoundFileOptions} from "@/utils/const.ts";
|
||||
@@ -89,7 +89,7 @@ export function usePlayWordAudio() {
|
||||
|
||||
function playAudio(word: string) {
|
||||
let url = `${PronunciationApi}${word}&type=2`
|
||||
if (settingStore.wordSoundType === 'uk') {
|
||||
if (settingStore.soundType === 'uk') {
|
||||
url = `${PronunciationApi}${word}&type=1`
|
||||
}
|
||||
audio.src = url
|
||||
@@ -139,25 +139,4 @@ export function getAudioFileUrl(name: string) {
|
||||
} else {
|
||||
return [`/sound/key-sounds/${name}.mp3`]
|
||||
}
|
||||
}
|
||||
|
||||
export function useWatchAllSound() {
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
watch([
|
||||
() => settingStore.wordSound,
|
||||
() => settingStore.keyboardSound,
|
||||
() => settingStore.effectSound,
|
||||
], (n) => {
|
||||
settingStore.allSound = n.some(v => v);
|
||||
})
|
||||
}
|
||||
|
||||
export function useChangeAllSound(e: boolean) {
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
settingStore.allSound = e
|
||||
settingStore.wordSound = e
|
||||
settingStore.keyboardSound = e
|
||||
settingStore.effectSound = e
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import {_getDictDataByUrl, cloneDeep} from "@/utils";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {useArticleOptions} from "@/hooks/dict.ts";
|
||||
import {genArticleSectionData, usePlaySentenceAudio} from "@/hooks/article.ts";
|
||||
import {getDefaultArticle, getDefaultDict} from "@/types/func.ts";
|
||||
import {getDefaultArticle, getDefaultDict, getDefaultWord} from "@/types/func.ts";
|
||||
import TypingArticle from "@/pages/pc/article/components/TypingArticle.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Panel from "@/pages/pc/components/Panel.vue";
|
||||
@@ -191,7 +191,7 @@ function wrong(word: Word) {
|
||||
let temp = word.word.toLowerCase();
|
||||
//过滤简单词
|
||||
if (settingStore.ignoreSimpleWord) {
|
||||
if (this.simpleWords.includes(temp)) return
|
||||
if (store.simpleWords.includes(temp)) return
|
||||
}
|
||||
if (!allWrongWords.has(word.word.toLowerCase())) {
|
||||
allWrongWords.add(word.word.toLowerCase())
|
||||
@@ -199,7 +199,7 @@ function wrong(word: Word) {
|
||||
}
|
||||
|
||||
if (!store.wrong.words.find((v: Word) => v.word.toLowerCase() === temp)) {
|
||||
store.wrong.words.push(word)
|
||||
store.wrong.words.push(getDefaultWord(word))
|
||||
store.wrong.length = store.wrong.words.length
|
||||
}
|
||||
}
|
||||
@@ -283,7 +283,7 @@ let audioRef = $ref<HTMLAudioElement>()
|
||||
const {playSentenceAudio} = usePlaySentenceAudio()
|
||||
|
||||
function play2(e) {
|
||||
if (settingStore.wordSound || e.handle) {
|
||||
if (settingStore.articleSound || e.handle) {
|
||||
playSentenceAudio(e.sentence, audioRef, articleData.article)
|
||||
}
|
||||
}
|
||||
@@ -370,7 +370,7 @@ function play2(e) {
|
||||
controls></audio>
|
||||
<div class="flex flex-col items-center justify-center gap-1">
|
||||
<div class="flex gap-2 center">
|
||||
<Switch v-model="settingStore.wordSound"/>
|
||||
<Switch v-model="settingStore.articleSound"/>
|
||||
<BaseIcon
|
||||
:title="`下一句(${settingStore.shortcutKeyMap[ShortcutKey.Next]})`"
|
||||
@click="skip">
|
||||
|
||||
@@ -11,10 +11,13 @@ import ContextMenu from '@imengyu/vue3-context-menu'
|
||||
import {getTranslateText} from "@/hooks/article.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import QuestionForm from "@/pages/pc/article/components/QuestionForm.vue";
|
||||
import {getDefaultArticle} from "@/types/func.ts";
|
||||
import {getDefaultArticle, getDefaultWord} from "@/types/func.ts";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import TypingWord from "@/pages/pc/article/components/TypingWord.vue";
|
||||
import Space from "@/pages/pc/article/components/Space.vue";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
import nlp from "compromise/three";
|
||||
import {nanoid} from "nanoid";
|
||||
|
||||
interface IProps {
|
||||
article: Article,
|
||||
@@ -74,6 +77,9 @@ const playBeep = usePlayBeep()
|
||||
const playCorrect = usePlayCorrect()
|
||||
const playKeyboardAudio = usePlayKeyboardAudio()
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
const {
|
||||
toggleWordCollect,
|
||||
} = useWordOptions()
|
||||
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
@@ -347,7 +353,7 @@ function hideSentence() {
|
||||
hoverIndex = {sectionIndex: -1, sentenceIndex: -1, wordIndex: -1}
|
||||
}
|
||||
|
||||
function onContextMenu(e: MouseEvent, sentence: Sentence, i, j,w) {
|
||||
function onContextMenu(e: MouseEvent, sentence: Sentence, i, j, w) {
|
||||
const selectedText = window.getSelection().toString();
|
||||
console.log(selectedText);
|
||||
//prevent the browser's default menu
|
||||
@@ -383,19 +389,48 @@ function onContextMenu(e: MouseEvent, sentence: Sentence, i, j,w) {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "播放",
|
||||
label: "添加到收藏",
|
||||
onClick: () => {
|
||||
emit('play', {sentence: sentence, handle: false})
|
||||
let word = props.article.sections[i][j].words[w]
|
||||
let doc = nlp(word.word)
|
||||
let text = word.word
|
||||
// 优先判断是不是动词
|
||||
if (doc.verbs().found) {
|
||||
text = doc.verbs().toInfinitive().text()
|
||||
}
|
||||
// 如果是名词(复数 → 单数)
|
||||
if (doc.nouns().found) {
|
||||
text = doc.nouns().toSingular().text()
|
||||
}
|
||||
if (!text.length) text = word.word
|
||||
console.log('text', text)
|
||||
toggleWordCollect(getDefaultWord({word: text, id: nanoid()}))
|
||||
Toast.success(text + ' 添加成功')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "复制",
|
||||
label: "复制句子",
|
||||
onClick: () => {
|
||||
navigator.clipboard.writeText(sentence.text).then(r => {
|
||||
Toast.success('已复制')
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "复制单词",
|
||||
onClick: () => {
|
||||
let word = props.article.sections[i][j].words[w]
|
||||
navigator.clipboard.writeText(word.word).then(r => {
|
||||
Toast.success('已复制')
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "播放句子",
|
||||
onClick: () => {
|
||||
emit('play', {sentence: sentence, handle: true})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "语法分析",
|
||||
onClick: () => {
|
||||
|
||||
@@ -158,7 +158,7 @@ onBeforeUnmount(onRelease)
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
opacity: .7;
|
||||
opacity: .3;
|
||||
|
||||
.btn, .input-inner {
|
||||
cursor: not-allowed;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import {computed, ref, watch} from "vue";
|
||||
import {ref, watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {getAudioFileUrl, useChangeAllSound, usePlayAudio, useWatchAllSound} from "@/hooks/sound.ts";
|
||||
import {getAudioFileUrl, usePlayAudio} from "@/hooks/sound.ts";
|
||||
import {getShortcutKey, useEventListener} from "@/hooks/event.ts";
|
||||
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, cloneDeep, shakeCommonDict} from "@/utils";
|
||||
import {DefaultShortcutKeyMap, ShortcutKey} from "@/types/types.ts";
|
||||
@@ -21,11 +21,8 @@ import RadioGroup from "@/pages/pc/components/base/radio/RadioGroup.vue";
|
||||
import Radio from "@/pages/pc/components/base/radio/Radio.vue";
|
||||
import InputNumber from "@/pages/pc/components/base/InputNumber.vue";
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import {get, set} from "idb-keyval";
|
||||
import BaseInput from "@/pages/pc/components/base/BaseInput.vue";
|
||||
import Textarea from "@/pages/pc/components/base/Textarea.vue";
|
||||
import SettingItem from "@/pages/pc/setting/SettingItem.vue";
|
||||
import Checkbox from "@/pages/pc/components/base/checkbox/Checkbox.vue";
|
||||
|
||||
const emit = defineEmits<{
|
||||
toggleDisabledDialogEscKey: [val: boolean]
|
||||
@@ -46,7 +43,6 @@ const simpleWords = $computed({
|
||||
}
|
||||
}
|
||||
})
|
||||
useWatchAllSound()
|
||||
|
||||
let editShortcutKey = $ref('')
|
||||
|
||||
@@ -174,26 +170,30 @@ function importOldData() {
|
||||
<div class="left mt-10">
|
||||
<div class="tabs">
|
||||
<div class="tab" :class="tabIndex === 0 && 'active'" @click="tabIndex = 0">
|
||||
<IconFluentAppsList24Regular width="20"/>
|
||||
<span>练习设置</span>
|
||||
<IconFluentSettings20Regular width="20"/>
|
||||
<span>通用练习设置</span>
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 1 && 'active'" @click="tabIndex = 1">
|
||||
<IconFluentHeadphones20Regular width="20"/>
|
||||
<span>音效设置</span>
|
||||
<IconFluentTextUnderlineDouble20Regular width="20"/>
|
||||
<span>单词练习设置</span>
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 2 && 'active'" @click="tabIndex = 2">
|
||||
<IconFluentBookLetter20Regular width="20"/>
|
||||
<span>文章练习设置</span>
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 3 && 'active'" @click="tabIndex = 3">
|
||||
<IconFluentKeyboardLayoutFloat20Regular width="20"/>
|
||||
<span>快捷键设置</span>
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 3 && 'active'" @click="tabIndex = 3">
|
||||
<div class="tab" :class="tabIndex === 4 && 'active'" @click="tabIndex = 4">
|
||||
<IconFluentDatabasePerson20Regular width="20"/>
|
||||
<span>数据管理</span>
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 4 && 'active'" @click="tabIndex = 4">
|
||||
<div class="tab" :class="tabIndex === 5 && 'active'" @click="tabIndex = 5">
|
||||
<IconFluentMailEdit20Regular width="20"/>
|
||||
<span>反馈</span>
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 5 && 'active'" @click="tabIndex = 5">
|
||||
<div class="tab" :class="tabIndex === 6 && 'active'" @click="tabIndex = 6">
|
||||
<IconFluentPerson20Regular width="20"/>
|
||||
<span>关于</span>
|
||||
</div>
|
||||
@@ -201,20 +201,10 @@ function importOldData() {
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="page-title text-align-center">设置</div>
|
||||
<!-- 通用练习设置-->
|
||||
<!-- 通用练习设置-->
|
||||
<!-- 通用练习设置-->
|
||||
<div v-if="tabIndex === 0">
|
||||
<SettingItem title="单词练习模式">
|
||||
<RadioGroup v-model="settingStore.wordPracticeMode" class="flex-col gap-0!">
|
||||
<Radio :value="0" label="智能模式,系统自动计算复习单词与默写单词"/>
|
||||
<Radio :value="1" label="自由模式,系统不强制复习与默写"/>
|
||||
</RadioGroup>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="显示上一个/下一个单词"
|
||||
desc="开启后,练习中会在上方显示上一个/下一个单词"
|
||||
>
|
||||
<Switch v-model="settingStore.showNearWord"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="忽略大小写"
|
||||
desc="开启后,输入时不区分大小写,如输入“hello”和“Hello”都会被认为是正确的"
|
||||
>
|
||||
@@ -227,75 +217,6 @@ function importOldData() {
|
||||
<Switch v-model="settingStore.allowWordTip"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="不默认显示练习设置弹框"
|
||||
desc="在词典详情页面,点击学习按钮后,是否显示练习设置弹框"
|
||||
>
|
||||
<Switch v-model="settingStore.disableShowPracticeSettingDialog"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="单词输入错误时,清空已输入内容"
|
||||
>
|
||||
<Switch v-model="settingStore.inputWrongClear"/>
|
||||
</SettingItem>
|
||||
|
||||
<div class="line" v-if="settingStore.autoNextWord"></div>
|
||||
<SettingItem title="自动切换下一个单词"
|
||||
desc="未开启自动切换时,当输入完成后请使用空格键切换下一个"
|
||||
>
|
||||
<Switch v-model="settingStore.autoNextWord"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="自动切换下一个单词时间"
|
||||
desc="正确输入单词后,自动跳转下一个单词的时间"
|
||||
v-if="settingStore.autoNextWord"
|
||||
>
|
||||
<InputNumber v-model="settingStore.waitTimeForChangeWord"
|
||||
:min="10"
|
||||
:max="100"
|
||||
type="number"
|
||||
/>
|
||||
<span class="ml-4">毫秒</span>
|
||||
</SettingItem>
|
||||
|
||||
<div class="line" v-if="settingStore.autoNextWord"></div>
|
||||
|
||||
|
||||
<SettingItem title="单词循环设置" class="gap-0!">
|
||||
<RadioGroup v-model="settingStore.repeatCount">
|
||||
<Radio :value="1" size="default">1</Radio>
|
||||
<Radio :value="2" size="default">2</Radio>
|
||||
<Radio :value="3" size="default">3</Radio>
|
||||
<Radio :value="5" size="default">5</Radio>
|
||||
<Radio :value="100" size="default">自定义</Radio>
|
||||
</RadioGroup>
|
||||
<div class="ml-2 center gap-space" v-if="settingStore.repeatCount === 100">
|
||||
<span>循环次数</span>
|
||||
<InputNumber v-model="settingStore.repeatCustomCount"
|
||||
:min="6"
|
||||
:max="15"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</SettingItem>
|
||||
|
||||
<div class="line"></div>
|
||||
|
||||
<SettingItem title="字体设置(仅单词练习界面生效)"/>
|
||||
<SettingItem title="外语字体">
|
||||
<Slider
|
||||
:min="10"
|
||||
:max="100"
|
||||
v-model="settingStore.fontSize.wordForeignFontSize"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.fontSize.wordForeignFontSize }}px</span>
|
||||
</SettingItem>
|
||||
<SettingItem title="中文字体">
|
||||
<Slider
|
||||
:min="10"
|
||||
:max="100"
|
||||
v-model="settingStore.fontSize.wordTranslateFontSize"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.fontSize.wordTranslateFontSize }}px</span>
|
||||
</SettingItem>
|
||||
|
||||
<div class="line"></div>
|
||||
<SettingItem title="简单词过滤"
|
||||
desc="开启后,练习单词中不会包含简单词;文章统计的总词数中不会包含简单词"
|
||||
@@ -311,18 +232,14 @@ function importOldData() {
|
||||
placeholder="多个单词用英文逗号隔号"
|
||||
v-model="simpleWords" :autosize="{minRows: 6, maxRows: 10}"/>
|
||||
</SettingItem>
|
||||
</div>
|
||||
<div v-if="tabIndex === 1">
|
||||
<SettingItem mainTitle="所有音效">
|
||||
<Switch v-model="settingStore.allSound" @change="useChangeAllSound"/>
|
||||
</SettingItem>
|
||||
|
||||
<!-- 音效-->
|
||||
<!-- 音效-->
|
||||
<!-- 音效-->
|
||||
<div class="line"></div>
|
||||
<SettingItem title="单词/句子自动发音">
|
||||
<Switch v-model="settingStore.wordSound"/>
|
||||
</SettingItem>
|
||||
<SettingItem main-title="音效"/>
|
||||
<SettingItem title="单词/句子发音口音">
|
||||
<Select v-model="settingStore.wordSoundType"
|
||||
<Select v-model="settingStore.soundType"
|
||||
placeholder="请选择"
|
||||
class="w-50!"
|
||||
>
|
||||
@@ -330,14 +247,6 @@ function importOldData() {
|
||||
<Option label="英音" value="uk"/>
|
||||
</Select>
|
||||
</SettingItem>
|
||||
<SettingItem title="音量">
|
||||
<Slider v-model="settingStore.wordSoundVolume"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.wordSoundVolume }}%</span>
|
||||
</SettingItem>
|
||||
<SettingItem title="倍速">
|
||||
<Slider v-model="settingStore.wordSoundSpeed" :step="0.1" :min="0.5" :max="3"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.wordSoundSpeed }}</span>
|
||||
</SettingItem>
|
||||
|
||||
<div class="line"></div>
|
||||
<SettingItem title="按键音">
|
||||
@@ -377,7 +286,148 @@ function importOldData() {
|
||||
<span class="w-10 pl-5">{{ settingStore.effectSoundVolume }}%</span>
|
||||
</SettingItem>
|
||||
</div>
|
||||
<div class="body" v-if="tabIndex === 2">
|
||||
|
||||
|
||||
<!-- 单词练习设置-->
|
||||
<!-- 单词练习设置-->
|
||||
<!-- 单词练习设置-->
|
||||
<div v-if="tabIndex === 1">
|
||||
<SettingItem title="练习模式">
|
||||
<RadioGroup v-model="settingStore.wordPracticeMode" class="flex-col gap-0!">
|
||||
<Radio :value="0" label="智能模式,系统自动计算复习单词与默写单词"/>
|
||||
<Radio :value="1" label="自由模式,系统不强制复习与默写"/>
|
||||
</RadioGroup>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="显示上一个/下一个单词"
|
||||
desc="开启后,练习中会在上方显示上一个/下一个单词"
|
||||
>
|
||||
<Switch v-model="settingStore.showNearWord"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="不默认显示练习设置弹框"
|
||||
desc="在词典详情页面,点击学习按钮后,是否显示练习设置弹框"
|
||||
>
|
||||
<Switch v-model="settingStore.disableShowPracticeSettingDialog"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="输入错误时,清空已输入内容"
|
||||
>
|
||||
<Switch v-model="settingStore.inputWrongClear"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="单词循环设置" class="gap-0!">
|
||||
<RadioGroup v-model="settingStore.repeatCount">
|
||||
<Radio :value="1" size="default">1</Radio>
|
||||
<Radio :value="2" size="default">2</Radio>
|
||||
<Radio :value="3" size="default">3</Radio>
|
||||
<Radio :value="5" size="default">5</Radio>
|
||||
<Radio :value="100" size="default">自定义</Radio>
|
||||
</RadioGroup>
|
||||
<div class="ml-2 center gap-space" v-if="settingStore.repeatCount === 100">
|
||||
<span>循环次数</span>
|
||||
<InputNumber v-model="settingStore.repeatCustomCount"
|
||||
:min="6"
|
||||
:max="15"
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
</SettingItem>
|
||||
|
||||
|
||||
<!-- 发音-->
|
||||
<!-- 发音-->
|
||||
<!-- 发音-->
|
||||
<div class="line"></div>
|
||||
<SettingItem mainTitle="音效"/>
|
||||
<SettingItem title="自动发音">
|
||||
<Switch v-model="settingStore.wordSound"/>
|
||||
</SettingItem>
|
||||
<SettingItem title="音量">
|
||||
<Slider v-model="settingStore.wordSoundVolume"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.wordSoundVolume }}%</span>
|
||||
</SettingItem>
|
||||
<SettingItem title="倍速">
|
||||
<Slider v-model="settingStore.wordSoundSpeed" :step="0.1" :min="0.5" :max="3"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.wordSoundSpeed }}</span>
|
||||
</SettingItem>
|
||||
|
||||
|
||||
<!-- 自动切换-->
|
||||
<!-- 自动切换-->
|
||||
<!-- 自动切换-->
|
||||
<div class="line"></div>
|
||||
<SettingItem mainTitle="自动切换"/>
|
||||
<SettingItem title="自动切换下一个单词"
|
||||
desc="未开启自动切换时,当输入完成后请使用空格键切换下一个"
|
||||
>
|
||||
<Switch v-model="settingStore.autoNextWord"/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem title="自动切换下一个单词时间"
|
||||
desc="正确输入单词后,自动跳转下一个单词的时间"
|
||||
>
|
||||
<InputNumber v-model="settingStore.waitTimeForChangeWord"
|
||||
:disabled="!settingStore.autoNextWord"
|
||||
:min="0"
|
||||
:max="10000"
|
||||
:step="100"
|
||||
type="number"
|
||||
/>
|
||||
<span class="ml-4">毫秒</span>
|
||||
</SettingItem>
|
||||
|
||||
|
||||
<!-- 字体设置-->
|
||||
<!-- 字体设置-->
|
||||
<!-- 字体设置-->
|
||||
<div class="line"></div>
|
||||
<SettingItem mainTitle="字体设置"/>
|
||||
<SettingItem title="外语字体">
|
||||
<Slider
|
||||
:min="10"
|
||||
:max="100"
|
||||
v-model="settingStore.fontSize.wordForeignFontSize"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.fontSize.wordForeignFontSize }}px</span>
|
||||
</SettingItem>
|
||||
<SettingItem title="中文字体">
|
||||
<Slider
|
||||
:min="10"
|
||||
:max="100"
|
||||
v-model="settingStore.fontSize.wordTranslateFontSize"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.fontSize.wordTranslateFontSize }}px</span>
|
||||
</SettingItem>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- 文章练习设置-->
|
||||
<!-- 文章练习设置-->
|
||||
<!-- 文章练习设置-->
|
||||
<div v-if="tabIndex === 2">
|
||||
<!-- 发音-->
|
||||
<!-- 发音-->
|
||||
<!-- 发音-->
|
||||
<div class="line"></div>
|
||||
<SettingItem mainTitle="音效"/>
|
||||
<SettingItem title="自动发音">
|
||||
<Switch v-model="settingStore.articleSound"/>
|
||||
</SettingItem>
|
||||
<SettingItem title="音量">
|
||||
<Slider v-model="settingStore.articleSoundVolume"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.articleSoundVolume }}%</span>
|
||||
</SettingItem>
|
||||
<SettingItem title="倍速">
|
||||
<Slider v-model="settingStore.articleSoundSpeed" :step="0.1" :min="0.5" :max="3"/>
|
||||
<span class="w-10 pl-5">{{ settingStore.articleSoundSpeed }}</span>
|
||||
</SettingItem>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="body" v-if="tabIndex === 3">
|
||||
<div class="row">
|
||||
<label class="main-title">功能</label>
|
||||
<div class="wrapper">快捷键(点击可修改)</div>
|
||||
@@ -388,7 +438,8 @@ function importOldData() {
|
||||
<div class="wrapper" @click="editShortcutKey = item[0]">
|
||||
<div class="set-key" v-if="editShortcutKey === item[0]">
|
||||
<input :value="item[1]?item[1]:'未设置快捷键'" readonly type="text" @blur="editShortcutKey = ''">
|
||||
<span @click.stop="editShortcutKey = ''">按键盘进行设置,<span class="text-red!">设置完成点击这里</span></span>
|
||||
<span @click.stop="editShortcutKey = ''">按键盘进行设置,<span
|
||||
class="text-red!">设置完成点击这里</span></span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="item[1]">{{ item[1] }}</div>
|
||||
@@ -404,7 +455,7 @@ function importOldData() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tabIndex === 3">
|
||||
<div v-if="tabIndex === 4">
|
||||
<div>
|
||||
目前用户的所有数据(自定义设置、自定义词典、自定义文章、学习进度等)
|
||||
<b class="text-red">仅保存在本地</b>。如果您需要在不同的设备、浏览器或者其他非官方部署上使用 {{ APP_NAME }},
|
||||
@@ -430,7 +481,7 @@ function importOldData() {
|
||||
</PopConfirm>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tabIndex === 4">
|
||||
<div v-if="tabIndex === 5">
|
||||
<div>
|
||||
给我发Email:<a href="mailto:zyronon@163.com">zyronon@163.com</a>
|
||||
</div>
|
||||
@@ -438,7 +489,7 @@ function importOldData() {
|
||||
<a :href="`${GITHUB}/issues`" target="_blank"> Issue </a>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="tabIndex === 5" class="center flex-col">
|
||||
<div v-if="tabIndex === 6" class="center flex-col">
|
||||
<h1>Type Words</h1>
|
||||
<p class="w-100 text-xl">
|
||||
感谢使用本项目!本项目是开源项目,如果觉得有帮助,请在 GitHub 点个 Star,您的支持是我持续改进的动力。
|
||||
|
||||
@@ -182,11 +182,11 @@ function mouseleave() {
|
||||
<div class="typing-word">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="flex gap-1 mt-26">
|
||||
<div class="phonetic" v-if="settingStore.wordSoundType === 'us' && word.phonetic0">[{{
|
||||
<div class="phonetic" v-if="settingStore.soundType === 'us' && word.phonetic0">[{{
|
||||
(settingStore.dictation && !showFullWord) ? '_'.repeat(word.phonetic0.length) : word.phonetic0
|
||||
}}]
|
||||
</div>
|
||||
<div class="phonetic" v-if="settingStore.wordSoundType === 'uk' && word.phonetic1">[{{
|
||||
<div class="phonetic" v-if="settingStore.soundType === 'uk' && word.phonetic1">[{{
|
||||
(settingStore.dictation && !showFullWord) ? '_'.repeat(word.phonetic1.length) : word.phonetic1
|
||||
}}]
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,14 @@ export interface SettingState {
|
||||
wordSound: boolean,
|
||||
wordSoundVolume: number,
|
||||
wordSoundSpeed: number,
|
||||
wordSoundType: string,
|
||||
soundType: string,
|
||||
|
||||
articleSound: boolean,
|
||||
articleSoundVolume: number,
|
||||
articleSoundSpeed: number,
|
||||
// articleSound: boolean,
|
||||
|
||||
|
||||
keyboardSound: boolean,
|
||||
keyboardSoundVolume: number,
|
||||
keyboardSoundFile: string,
|
||||
@@ -44,6 +51,7 @@ export interface SettingState {
|
||||
disableShowPracticeSettingDialog: boolean // 不默认显示练习设置弹框
|
||||
autoNextWord: boolean //自动切换下一个单词
|
||||
inputWrongClear: boolean //单词输入错误,清空已输入内容
|
||||
|
||||
}
|
||||
|
||||
export const getDefaultSettingState = (): SettingState => ({
|
||||
@@ -52,10 +60,16 @@ export const getDefaultSettingState = (): SettingState => ({
|
||||
sideExpand: false,
|
||||
|
||||
allSound: true,
|
||||
|
||||
wordSound: true,
|
||||
wordSoundVolume: 100,
|
||||
wordSoundSpeed: 1,
|
||||
wordSoundType: 'us',
|
||||
|
||||
articleSound: true,
|
||||
articleSoundVolume: 100,
|
||||
articleSoundSpeed: 1,
|
||||
|
||||
soundType: 'us',
|
||||
keyboardSound: true,
|
||||
keyboardSoundVolume: 100,
|
||||
keyboardSoundFile: '机械键盘2',
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import {Article, ArticleWord, Dict, DictType, Word} from "@/types/types.ts";
|
||||
import {shallowReactive} from "vue";
|
||||
import {cloneDeep} from "@/utils";
|
||||
import {nanoid} from "nanoid";
|
||||
|
||||
export function getDefaultWord(val: Partial<Word> = {}): Word {
|
||||
return {
|
||||
custom: false,
|
||||
id: nanoid(6),
|
||||
"word": "",
|
||||
"phonetic0": "",
|
||||
"phonetic1": "",
|
||||
|
||||
@@ -14,7 +14,7 @@ export const SAVE_DICT_KEY = {
|
||||
}
|
||||
export const SAVE_SETTING_KEY = {
|
||||
key: 'typing-word-setting',
|
||||
version: 13
|
||||
version: 14
|
||||
}
|
||||
export const EXPORT_DATA_KEY = {
|
||||
key: 'typing-word-export',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {SAVE_DICT_KEY, SAVE_SETTING_KEY} from "@/utils/const.ts";
|
||||
import {BaseState, DefaultBaseState} from "@/stores/base.ts";
|
||||
import {getDefaultSettingState} from "@/stores/setting.ts";
|
||||
import {getDefaultSettingState, SettingState} from "@/stores/setting.ts";
|
||||
import {Dict, DictId, DictResource, DictType} from "@/types/types.ts";
|
||||
import {useRouter} from "vue-router";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
@@ -45,10 +45,7 @@ export function checkAndUpgradeSaveDict(val: any) {
|
||||
let version = Number(data.version)
|
||||
// console.log('state', state)
|
||||
if (version === SAVE_DICT_KEY.version) {
|
||||
//防止人为删除数据,导致数据不完整报错
|
||||
for (const [key, value] of Object.entries(defaultState)) {
|
||||
if (state[key] !== undefined) defaultState[key] = state[key]
|
||||
}
|
||||
checkRiskKey(defaultState, state)
|
||||
return defaultState
|
||||
} else {
|
||||
if (version === 3) {
|
||||
@@ -186,10 +183,7 @@ export function checkAndUpgradeSaveDict(val: any) {
|
||||
}
|
||||
})
|
||||
}
|
||||
//防止人为删除数据,导致数据不完整报错
|
||||
for (const [key, value] of Object.entries(defaultState)) {
|
||||
if (state[key] !== undefined) defaultState[key] = state[key]
|
||||
}
|
||||
checkRiskKey(defaultState, state)
|
||||
return defaultState
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -213,7 +207,7 @@ export function checkAndUpgradeSaveSetting(val: any) {
|
||||
data = val
|
||||
}
|
||||
if (!data.version) return defaultState
|
||||
let state: any = data.val
|
||||
let state: SettingState & { [key: string]: any } = data.val
|
||||
if (typeof state !== 'object') return defaultState
|
||||
state.load = false
|
||||
let version = Number(data.version)
|
||||
@@ -221,6 +215,9 @@ export function checkAndUpgradeSaveSetting(val: any) {
|
||||
checkRiskKey(defaultState, state)
|
||||
return defaultState
|
||||
} else {
|
||||
if (version === 13) {
|
||||
defaultState.soundType = state.soundType
|
||||
}
|
||||
//为了保持永远是最新的快捷键选项列表,但保留住用户的自定义设置,去掉无效的快捷键选项
|
||||
//例: 2版本,可能有快捷键A。3版本没有了
|
||||
checkRiskKey(defaultState.shortcutKeyMap, state.shortcutKeyMap)
|
||||
|
||||
Reference in New Issue
Block a user