设计背词逻辑
This commit is contained in:
@@ -7,8 +7,23 @@ import Tooltip from "@/components/Tooltip.vue";
|
||||
import Fireworks from "@/components/Fireworks.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {DictType} from "@/types.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {onMounted} from "vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
let statModalIsOpen = $ref(false)
|
||||
let currentStat = $ref({
|
||||
wrongNumber: -1,
|
||||
correctRate: -1
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
emitter.on(EventKey.openStatModal, () => {
|
||||
statModalIsOpen = true
|
||||
store.lastStatistics.endDate = Date.now()
|
||||
currentStat = store.lastStatistics
|
||||
})
|
||||
})
|
||||
|
||||
function write() {
|
||||
store.isDictation = true
|
||||
@@ -19,9 +34,17 @@ function write() {
|
||||
function repeat() {
|
||||
store.currentDict.wordIndex = 0
|
||||
store.currentWrongDict.wordList = []
|
||||
store.statModalIsOpen = false
|
||||
store.lastStatistics.correctNumber = -1
|
||||
store.lastStatistics.correctRate = -1
|
||||
statModalIsOpen = false
|
||||
let stat = store.currentDict.dictStatistics[store.currentDict.dictStatistics.length - 1]
|
||||
if (stat.statistics.length) {
|
||||
stat.statistics.push({
|
||||
startDate: Date.now(),//开始日期
|
||||
endDate: -1,
|
||||
correctRate: -1,
|
||||
wrongNumber: -1
|
||||
})
|
||||
}
|
||||
emitter.on(EventKey.resetWord)
|
||||
}
|
||||
|
||||
function next() {
|
||||
@@ -30,7 +53,7 @@ function next() {
|
||||
}
|
||||
|
||||
function repeatWrong() {
|
||||
if (store.currentDictType !== DictType.currentWrongDict){
|
||||
if (store.currentDictType !== DictType.currentWrongDict) {
|
||||
store.lastDictType = store.currentDictType
|
||||
}
|
||||
store.currentDictType = DictType.currentWrongDict
|
||||
@@ -38,24 +61,26 @@ function repeatWrong() {
|
||||
store.currentWrongDict.chapterIndex = 0
|
||||
store.currentWrongDict.wordIndex = 0
|
||||
store.currentWrongDict.wordList = []
|
||||
store.statModalIsOpen = false
|
||||
statModalIsOpen = false
|
||||
emitter.on(EventKey.resetWord)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal v-model="store.statModalIsOpen" @close="next">
|
||||
<Modal v-model="statModalIsOpen" @close="next">
|
||||
<div class="statistics">
|
||||
<header>
|
||||
<div class="title">{{ store.currentDict.name }} 第{{ store.currentDict.chapterIndex + 1 }}章</div>
|
||||
<div class="title">{{ store.currentDict.name }} {{ store.chapterName }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="rings">
|
||||
<Ring
|
||||
:value="store.lastStatistics.correctRate + '%'"
|
||||
:value="currentStat.correctRate + '%'"
|
||||
desc="正确率"
|
||||
:percentage="store.lastStatistics.correctRate"/>
|
||||
:percentage="currentStat.correctRate"/>
|
||||
<Ring
|
||||
:value="store.lastStatistics.correctNumber"
|
||||
:value="currentStat.wrongNumber"
|
||||
desc="正确数"
|
||||
:percentage="0"
|
||||
/>
|
||||
|
||||
@@ -11,6 +11,7 @@ import {Swiper as SwiperClass} from "swiper/types"
|
||||
import {Dict, DictType} from "@/types.ts"
|
||||
import PopConfirm from "@/components/PopConfirm.vue"
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
|
||||
const store = useBaseStore()
|
||||
const swiperIns0: SwiperClass = $ref(null as any)
|
||||
@@ -22,33 +23,43 @@ function slideTo(index: number) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
slideTo(1)
|
||||
}, 300)
|
||||
emitter.on(EventKey.openSide, () => {
|
||||
store.sideIsOpen = !store.sideIsOpen
|
||||
if (store.sideIsOpen) {
|
||||
switch (store.currentDictType) {
|
||||
case DictType.newWordDict:
|
||||
return tabIndex = 2;
|
||||
case DictType.skipWordDict:
|
||||
return tabIndex = 4;
|
||||
case DictType.allWrongDict:
|
||||
return tabIndex = 3;
|
||||
case DictType.currentWrongDict:
|
||||
return tabIndex = 0;
|
||||
case DictType.inner:
|
||||
case DictType.custom:
|
||||
return tabIndex = 1;
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function changeDict(dict: Dict, i: number) {
|
||||
if (store.currentDictType !== dict.type) {
|
||||
store.currentDictType = dict.type
|
||||
}
|
||||
store.currentDict.wordIndex = i
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<Transition name="fade">
|
||||
<div class="side" v-if="store.sideIsOpen">
|
||||
<header>
|
||||
<div class="tabs">
|
||||
<div class="tab" v-if="store.isWrongMode" :class="tabIndex===0&&'active'" @click="slideTo(0)">错词模式</div>
|
||||
<div class="tab" v-if="store.isWrongMode" :class="tabIndex===0&&'active'" @click="slideTo(0)">
|
||||
{{ store.currentWrongDict.name }}
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex===1&&'active'" @click="slideTo(1)">单词表</div>
|
||||
<div class="tab" :class="tabIndex===2&&'active'" @click="slideTo(2)">生词本</div>
|
||||
<div class="tab" :class="tabIndex===3&&'active'" @click="slideTo(3)">纠错本</div>
|
||||
<div class="tab" :class="tabIndex===4&&'active'" @click="slideTo(4)">已忽略</div>
|
||||
<div class="tab" :class="tabIndex===2&&'active'" @click="slideTo(2)">{{ store.newWordDict.name }}</div>
|
||||
<div class="tab" :class="tabIndex===3&&'active'" @click="slideTo(3)">{{ store.allWrongDict.name }}</div>
|
||||
<div class="tab" :class="tabIndex===4&&'active'" @click="slideTo(4)">{{ store.skipWordDict.name }}</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="side-content">
|
||||
<swiper @swiper="e=>swiperIns0 = e" class="mySwiper" :allow-touch-move="false">
|
||||
<swiper :initial-slide="tabIndex" @swiper="e=>swiperIns0 = e" class="mySwiper" :allow-touch-move="false">
|
||||
<swiper-slide>
|
||||
<div class="page0">
|
||||
<header>
|
||||
|
||||
@@ -31,8 +31,9 @@ import IconEyeSlash from '~icons/heroicons/eye-slash-solid'
|
||||
|
||||
import IconRepeat from '~icons/tabler/repeat'
|
||||
import IconRepeatOff from '~icons/tabler/repeat-off'
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
|
||||
const { toggle} = useTheme()
|
||||
const {toggle} = useTheme()
|
||||
const store = useBaseStore()
|
||||
const showFeedbackModal = $ref(false)
|
||||
const showSettingModal = $ref(false)
|
||||
@@ -41,12 +42,13 @@ const showDictModal = $ref(false)
|
||||
function t() {
|
||||
console.log('t')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header :class="!store.setting.showToolbar && 'hide'">
|
||||
<div class="info" @click="showDictModal = true">
|
||||
{{ store.currentDict.name }} 第{{ store.currentDict.chapterIndex + 1 }}章
|
||||
{{ store.currentDict.name }} {{ store.chapterName }}
|
||||
</div>
|
||||
<div class="options">
|
||||
<Tooltip title="切换主题">
|
||||
@@ -95,12 +97,12 @@ function t() {
|
||||
<IconCog6Tooth @click="showSettingModal = true"></IconCog6Tooth>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<div class="my-button" @click="store.statModalIsOpen = true">ok</div>
|
||||
<div class="my-button" @click="emitter.emit(EventKey.openStatModal)">ok</div>
|
||||
|
||||
<Tooltip title="单词本">
|
||||
<menu-fold class="menu" @click="store.sideIsOpen = !store.sideIsOpen"
|
||||
theme="outline" size="20" fill="#929596"
|
||||
:strokeWidth="2"/>
|
||||
<IconWrapper>
|
||||
<menu-fold class="menu" @click="emitter.emit(EventKey.openSide)"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Tooltip :title="store.setting.showToolbar?'收起':'展开'">
|
||||
|
||||
@@ -28,7 +28,9 @@ import BaseButton from "@/components/BaseButton.vue";
|
||||
import Type from "@/components/Type.vue";
|
||||
import {
|
||||
Down,
|
||||
Delete,
|
||||
} from "@icon-park/vue-next"
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
|
||||
let input = $ref('')
|
||||
let wrong = $ref('')
|
||||
@@ -50,12 +52,16 @@ const keyMap = {
|
||||
Collect: 'Enter',
|
||||
}
|
||||
|
||||
const restWord = $computed(() => {
|
||||
const resetWord = $computed(() => {
|
||||
return store.word.name.slice(input.length + wrong.length)
|
||||
})
|
||||
onMounted(() => {
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
window.addEventListener('keyup', onKeyUp)
|
||||
|
||||
emitter.on(EventKey.resetWord, () => {
|
||||
input = ''
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -68,18 +74,44 @@ watch(store.$state, (n) => {
|
||||
localStorage.setItem(SaveKey, JSON.stringify(n))
|
||||
})
|
||||
|
||||
|
||||
function repeatWrong() {
|
||||
if (store.currentDictType !== DictType.currentWrongDict) {
|
||||
store.lastDictType = store.currentDictType
|
||||
}
|
||||
store.currentDictType = DictType.currentWrongDict
|
||||
store.currentWrongDict.chapterList = [store.currentWrongDict.wordList]
|
||||
store.currentWrongDict.chapterIndex = 0
|
||||
store.currentWrongDict.wordIndex = 0
|
||||
store.currentWrongDict.wordList = []
|
||||
store.currentWrongDict.statistics = {
|
||||
startDate: Date.now(),//开始日期
|
||||
endDate: -1,
|
||||
correctRate: -1,
|
||||
wrongNumber: -1
|
||||
}
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (store.currentDict.wordIndex === store.chapter.length - 1) {
|
||||
if (store.currentDict.chapterIndex !== store.currentDict.chapterList.length - 1) {
|
||||
// store.currentDict.wordIndex = 0
|
||||
store.currentDict.wordIndex++
|
||||
// store.currentDict.chapterIndex++
|
||||
console.log('这一章节完了')
|
||||
store.statModalIsOpen = true
|
||||
if (store.currentWrongDict.wordList.length) {
|
||||
repeatWrong()
|
||||
}
|
||||
// emitter.emit(EventKey.openStatModal)
|
||||
} else {
|
||||
console.log('这本书完了')
|
||||
store.statModalIsOpen = true
|
||||
return
|
||||
if (store.currentDictType === DictType.currentWrongDict) {
|
||||
if ( store.currentWrongDict.wordList.length){
|
||||
repeatWrong()
|
||||
}else {
|
||||
emitter.emit(EventKey.openStatModal)
|
||||
}
|
||||
} else {
|
||||
emitter.emit(EventKey.openStatModal)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
store.currentDict.wordIndex++
|
||||
@@ -93,18 +125,18 @@ function next() {
|
||||
// window.speechSynthesis.speak(msg);
|
||||
|
||||
console.log('这个词完了')
|
||||
if (store.currentDict.wordIndex) {
|
||||
store.lastStatistics.wrongNumber = store.currentDict.wordIndex - store.currentWrongDict.wordList.length
|
||||
store.lastStatistics.correctRate = Math.trunc(((store.currentDict.wordIndex - store.currentWrongDict.wordList.length) / (store.currentDict.wordIndex)) * 100)
|
||||
} else {
|
||||
store.lastStatistics.correctRate = -1
|
||||
store.lastStatistics.wrongNumber = -1
|
||||
}
|
||||
}
|
||||
if ([DictType.custom, DictType.inner].includes(store.currentDictType) && store.skipWordNames.includes(store.word.name)) {
|
||||
next()
|
||||
}
|
||||
wrong = input = ''
|
||||
if (store.currentDict.wordIndex) {
|
||||
store.lastStatistics.correctNumber = store.currentDict.wordIndex - store.currentWrongDict.wordList.length
|
||||
store.lastStatistics.correctRate = Math.trunc(((store.currentDict.wordIndex - store.currentWrongDict.wordList.length) / (store.currentDict.wordIndex)) * 100)
|
||||
} else {
|
||||
store.lastStatistics.correctRate = -1
|
||||
store.lastStatistics.correctNumber = -1
|
||||
}
|
||||
}
|
||||
|
||||
function onKeyUp(e: KeyboardEvent) {
|
||||
@@ -139,7 +171,6 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
playCorrect()
|
||||
setTimeout(next, 300)
|
||||
}
|
||||
|
||||
} else {
|
||||
// console.log('e', e)
|
||||
switch (e.key) {
|
||||
@@ -183,7 +214,7 @@ const progress = $computed(() => {
|
||||
return ((store.currentDict.wordIndex / store.chapter.length) * 100)
|
||||
})
|
||||
|
||||
const { toggle} = useTheme()
|
||||
const {toggle} = useTheme()
|
||||
|
||||
function format(val: number, suffix: string = '') {
|
||||
return val === -1 ? '-' : (val + suffix)
|
||||
@@ -200,10 +231,10 @@ function format(val: number, suffix: string = '') {
|
||||
<span class="wrong" v-if="wrong">{{ wrong }}</span>
|
||||
<template v-if="store.isDictation">
|
||||
<span class="letter" v-if="!showFullWord"
|
||||
@mouseenter="showFullWord = true">{{ restWord.split('').map(v => '_').join('') }}</span>
|
||||
<span class="letter" v-else @mouseleave="showFullWord = false">{{ restWord }}</span>
|
||||
@mouseenter="showFullWord = true">{{ resetWord.split('').map(v => '_').join('') }}</span>
|
||||
<span class="letter" v-else @mouseleave="showFullWord = false">{{ resetWord }}</span>
|
||||
</template>
|
||||
<span class="letter" v-else>{{ restWord }}</span>
|
||||
<span class="letter" v-else>{{ resetWord }}</span>
|
||||
</div>
|
||||
<div class="audio" @click="playAudio(store.word.name)">播放</div>
|
||||
</div>
|
||||
@@ -237,9 +268,9 @@ function format(val: number, suffix: string = '') {
|
||||
<div class="name">输入数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ format(store.lastStatistics.correctNumber) }}</div>
|
||||
<div class="num">{{ format(store.currentWrongDict.wordList.length) }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">正确数</div>
|
||||
<div class="name">错误数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ format(store.lastStatistics.correctRate, '%') }}</div>
|
||||
|
||||
Reference in New Issue
Block a user