重构数据结构
This commit is contained in:
10
src/App.vue
10
src/App.vue
@@ -5,8 +5,9 @@ import Type from "@/components/Type.vue";
|
||||
import Side from "@/components/Side.vue";
|
||||
import Statistics from "@/components/Modal/Statistics.vue";
|
||||
import Backgorund from "@/components/Backgorund.vue";
|
||||
import {onMounted} from "vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {SaveKey} from "@/types.ts"
|
||||
|
||||
const store = useBaseStore()
|
||||
// 查询当前系统主题颜色
|
||||
@@ -19,6 +20,11 @@ function followSystem() {
|
||||
document.documentElement.setAttribute('data-theme', theme)
|
||||
}
|
||||
|
||||
watch(store.$state, (n) => {
|
||||
// console.log('state', JSON.stringify(n.current, null, 2))
|
||||
localStorage.setItem(SaveKey, JSON.stringify(n))
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
store.init()
|
||||
if (store.theme !== 'auto') {
|
||||
@@ -28,7 +34,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <Backgorund/>-->
|
||||
<!-- <Backgorund/>-->
|
||||
<div class="main-page">
|
||||
<div class="center">
|
||||
<Toolbar/>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
--color-item-bg: white;
|
||||
--color-item-hover: white;
|
||||
--color-item-active: rgb(75, 110, 175);
|
||||
--toolbar-width: 600rem;
|
||||
--toolbar-width: 700rem;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import Modal from "@/components/Modal/Modal.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {KeyboardOne, Like, ShareThree, Tea} from '@icon-park/vue-next'
|
||||
import {Like, ShareThree, Tea} from '@icon-park/vue-next'
|
||||
import Ring from "@/components/Ring.vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import Fireworks from "@/components/Fireworks.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {DictType} from "@/types.ts";
|
||||
import {DefaultStatistics, Statistics} from "@/types.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {onMounted} from "vue";
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {cloneDeep} from "lodash";
|
||||
|
||||
const store = useBaseStore()
|
||||
let statModalIsOpen = $ref(false)
|
||||
let currentStat = $ref({
|
||||
wrongNumber: -1,
|
||||
correctRate: -1
|
||||
})
|
||||
let currentStat = reactive<Statistics>(cloneDeep(DefaultStatistics))
|
||||
|
||||
onMounted(() => {
|
||||
emitter.on(EventKey.openStatModal, () => {
|
||||
statModalIsOpen = true
|
||||
store.lastStatistics.endDate = Date.now()
|
||||
currentStat = store.lastStatistics
|
||||
currentStat = cloneDeep(store.current.statistics)
|
||||
currentStat.endDate = Date.now()
|
||||
currentStat.spend = Date.now() - currentStat.startDate
|
||||
currentStat.wrongWordNumber = store.current.originWrongWords.length
|
||||
currentStat.correctRate = 100 - Math.trunc((currentStat.wrongWordNumber / currentStat.wordNumber) * 100)
|
||||
console.log(cloneDeep(currentStat))
|
||||
store.currentDict.statistics.push(currentStat)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -32,19 +35,9 @@ function write() {
|
||||
|
||||
//TODO 需要判断是否已忽略
|
||||
function repeat() {
|
||||
store.currentDict.wordIndex = 0
|
||||
store.currentWrongDict.wordList = []
|
||||
store.setCurrentWord(store.chapter, true)
|
||||
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)
|
||||
emitter.emit(EventKey.resetWord)
|
||||
}
|
||||
|
||||
function next() {
|
||||
@@ -52,26 +45,13 @@ function next() {
|
||||
repeat()
|
||||
}
|
||||
|
||||
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 = []
|
||||
statModalIsOpen = false
|
||||
emitter.on(EventKey.resetWord)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal v-model="statModalIsOpen" @close="next">
|
||||
<div class="statistics">
|
||||
<header>
|
||||
<div class="title">{{ store.currentDict.name }} {{ store.chapterName }}</div>
|
||||
<div class="title">{{ store.currentDict.name }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="rings">
|
||||
@@ -80,24 +60,24 @@ function repeatWrong() {
|
||||
desc="正确率"
|
||||
:percentage="currentStat.correctRate"/>
|
||||
<Ring
|
||||
:value="currentStat.wrongNumber"
|
||||
desc="正确数"
|
||||
:value="currentStat.wrongWordNumber"
|
||||
desc="错误数"
|
||||
:percentage="0"
|
||||
/>
|
||||
<Ring
|
||||
:value="store.currentDict.wordIndex"
|
||||
desc="输入数"
|
||||
:value="currentStat.wordNumber"
|
||||
desc="单词总数"
|
||||
:percentage="0"
|
||||
style="margin-bottom: 0;"/>
|
||||
</div>
|
||||
<div class="result">
|
||||
<div class="wrong-words-wrapper">
|
||||
<div class="wrong-words">
|
||||
<div class="word" v-for="i in store.currentWrongDict.wordList">{{ i.name }}</div>
|
||||
<div class="word" v-for="i in store.current.originWrongWords">{{ i.name }}</div>
|
||||
<!-- <div class="word" v-for="i in 100">{{ i }}</div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="notice" v-if="!store.currentWrongDict.wordList.length">
|
||||
<div class="notice" v-if="!store.current.originWrongWords.length">
|
||||
<!-- <div class="notice">-->
|
||||
<like theme="filled" size="20" fill="#ffffff" :strokeWidth="2"/>
|
||||
表现不错,全对了!
|
||||
@@ -122,16 +102,13 @@ function repeatWrong() {
|
||||
<BaseButton keyboard="Alt + Enter" @click="repeat">
|
||||
重复本章
|
||||
</BaseButton>
|
||||
<BaseButton keyboard="Enter" @click="repeatWrong">
|
||||
重复错词
|
||||
</BaseButton>
|
||||
<BaseButton keyboard="Tab" @click="next">
|
||||
下一章
|
||||
</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Fireworks v-if="store.statModalIsOpen"/>
|
||||
<Fireworks v-if="statModalIsOpen"/>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
@import "@/assets/css/style";
|
||||
|
||||
@@ -69,6 +69,7 @@ $w2: calc($w / 2);
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 14rem;
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
|
||||
const store = useBaseStore()
|
||||
const swiperIns0: SwiperClass = $ref(null as any)
|
||||
let tabIndex = $ref(1)
|
||||
let tabIndex = $ref(0)
|
||||
provide('tabIndex', computed(() => tabIndex))
|
||||
|
||||
function slideTo(index: number) {
|
||||
@@ -26,18 +26,16 @@ onMounted(() => {
|
||||
emitter.on(EventKey.openSide, () => {
|
||||
store.sideIsOpen = !store.sideIsOpen
|
||||
if (store.sideIsOpen) {
|
||||
switch (store.currentDictType) {
|
||||
switch (store.current.dictType) {
|
||||
case DictType.newWordDict:
|
||||
return tabIndex = 2;
|
||||
return tabIndex = 1;
|
||||
case DictType.skipWordDict:
|
||||
return tabIndex = 4;
|
||||
case DictType.allWrongDict:
|
||||
return tabIndex = 3;
|
||||
case DictType.currentWrongDict:
|
||||
return tabIndex = 0;
|
||||
case DictType.wrongWordDict:
|
||||
return tabIndex = 2;
|
||||
case DictType.inner:
|
||||
case DictType.custom:
|
||||
return tabIndex = 1;
|
||||
return tabIndex = 0;
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -49,40 +47,14 @@ onMounted(() => {
|
||||
<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)">
|
||||
{{ 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)">{{ 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 class="tab" :class="tabIndex===0&&'active'" @click="slideTo(0)">{{ store.dict.name }}</div>
|
||||
<div class="tab" :class="tabIndex===1&&'active'" @click="slideTo(1)">{{ store.newWordDict.name }}</div>
|
||||
<div class="tab" :class="tabIndex===2&&'active'" @click="slideTo(2)">{{ store.wrongWordDict.name }}</div>
|
||||
<div class="tab" :class="tabIndex===3&&'active'" @click="slideTo(3)">{{ store.skipWordDict.name }}</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="side-content">
|
||||
<swiper :initial-slide="tabIndex" @swiper="e=>swiperIns0 = e" class="mySwiper" :allow-touch-move="false">
|
||||
<swiper-slide>
|
||||
<div class="page0">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.currentDict.chapterList[0].length }}</div>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(e:number) => store.changeDict(store.currentWrongDict,-1,e)"
|
||||
:isActive="store.sideIsOpen && tabIndex === 0"
|
||||
:list="store.currentDict.chapterList[0]??[]"
|
||||
:activeIndex="store.currentDict.wordIndex"/>
|
||||
<footer v-if="![DictType.custom,DictType.inner].includes(store.currentDictType)">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="store.changeDict(store.dict)"
|
||||
>
|
||||
<div class="my-button">
|
||||
切换
|
||||
</div>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
<swiper-slide>
|
||||
<div class="page0">
|
||||
<header>
|
||||
@@ -91,10 +63,10 @@ onMounted(() => {
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(e:number) => store.changeDict(store.dict,-1,e)"
|
||||
:isActive="store.sideIsOpen && tabIndex === 1"
|
||||
:list="store.dict.chapterList[store.dict.chapterIndex]??[]"
|
||||
:activeIndex="store.dict.wordIndex"/>
|
||||
<footer v-if="![DictType.custom,DictType.inner].includes(store.currentDictType)">
|
||||
:isActive="store.sideIsOpen && tabIndex === 0"
|
||||
:list="store.dict.chapters[store.dict.chapterIndex]??[]"
|
||||
:activeIndex="store.dict.chapterWordIndex"/>
|
||||
<footer v-if="![DictType.custom,DictType.inner].includes(store.current.dictType)">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="store.changeDict(store.dict)"
|
||||
@@ -109,15 +81,15 @@ onMounted(() => {
|
||||
<swiper-slide>
|
||||
<div class="page0">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.newWordDict.wordList.length }}</div>
|
||||
<div class="dict-name">总词数:{{ store.newWordDict.originWords.length }}</div>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(e:number) => store.changeDict(store.newWordDict,-1,e)"
|
||||
:isActive="store.sideIsOpen && tabIndex === 2"
|
||||
:list="store.newWordDict.wordList"
|
||||
:activeIndex="store.newWordDict.wordIndex"/>
|
||||
<footer v-if="store.currentDictType !== DictType.newWordDict && store.newWordDict.wordList.length">
|
||||
:isActive="store.sideIsOpen && tabIndex === 1"
|
||||
:list="store.newWordDict.originWords"
|
||||
:activeIndex="store.newWordDict.chapterWordIndex"/>
|
||||
<footer v-if="store.current.dictType !== DictType.newWordDict && store.newWordDict.originWords.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="store.changeDict(store.newWordDict)"
|
||||
@@ -133,18 +105,18 @@ onMounted(() => {
|
||||
<div class="page0">
|
||||
<header>
|
||||
<a href="" target="_blank"></a>
|
||||
<div class="dict-name">总词数:{{ store.allWrongDict.wordList.length }}</div>
|
||||
<div class="dict-name">总词数:{{ store.wrongWordDict.originWords.length }}</div>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(e:number) => store.changeDict(store.allWrongDict,-1,e)"
|
||||
:isActive="store.sideIsOpen && tabIndex === 3"
|
||||
:list="store.allWrongDict.wordList"
|
||||
:activeIndex="store.allWrongDict.wordIndex"/>
|
||||
<footer v-if="store.currentDictType !== DictType.allWrongDict && store.allWrongDict.wordList.length">
|
||||
@change="(e:number) => store.changeDict(store.wrongWordDict,-1,e)"
|
||||
:isActive="store.sideIsOpen && tabIndex === 2"
|
||||
:list="store.wrongWordDict.originWords"
|
||||
:activeIndex="store.wrongWordDict.chapterWordIndex"/>
|
||||
<footer v-if="store.current.dictType !== DictType.wrongWordDict && store.wrongWordDict.originWords.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="store.changeDict(store.allWrongDict)"
|
||||
@confirm="store.changeDict(store.wrongWordDict)"
|
||||
>
|
||||
<BaseButton>
|
||||
切换
|
||||
@@ -156,15 +128,15 @@ onMounted(() => {
|
||||
<swiper-slide>
|
||||
<div class="page0">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.skipWordDict.wordList.length }}</div>
|
||||
<div class="dict-name">总词数:{{ store.skipWordDict.originWords.length }}</div>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(e:number) => store.changeDict(store.skipWordDict,-1,e)"
|
||||
:isActive="store.sideIsOpen && tabIndex === 4"
|
||||
:list="store.skipWordDict.wordList"
|
||||
:activeIndex="store.skipWordDict.wordIndex"/>
|
||||
<footer v-if="store.currentDictType !== DictType.skipWordDict && store.skipWordDict.wordList.length">
|
||||
:isActive="store.sideIsOpen && tabIndex === 3"
|
||||
:list="store.skipWordDict.originWords"
|
||||
:activeIndex="store.skipWordDict.chapterWordIndex"/>
|
||||
<footer v-if="store.current.dictType !== DictType.skipWordDict && store.skipWordDict.originWords.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="store.changeDict(store.skipWordDict)"
|
||||
|
||||
@@ -48,7 +48,7 @@ function t() {
|
||||
<template>
|
||||
<header :class="!store.setting.showToolbar && 'hide'">
|
||||
<div class="info" @click="showDictModal = true">
|
||||
{{ store.currentDict.name }} {{ store.chapterName }}
|
||||
{{ store.dictTitle }}
|
||||
</div>
|
||||
<div class="options">
|
||||
<Tooltip title="切换主题">
|
||||
@@ -136,7 +136,7 @@ header {
|
||||
transition: all .3s;
|
||||
|
||||
.info {
|
||||
font-size: 18rem;
|
||||
font-size: 16rem;
|
||||
color: var(--color-font-1);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
@@ -63,62 +63,43 @@ onUnmounted(() => {
|
||||
window.removeEventListener('keyup', onKeyUp)
|
||||
})
|
||||
|
||||
watch(store.$state, (n) => {
|
||||
localStorage.setItem(SaveKey, JSON.stringify(n))
|
||||
})
|
||||
|
||||
|
||||
function repeatWrong() {
|
||||
store.current.words = cloneDeep(store.current.wrongWords)
|
||||
store.current.index = 0
|
||||
store.current.wrongWords = []
|
||||
store.current.statistics = {
|
||||
startDate: -1,
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
wordNumber: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (store.current.wrongWords.length) {
|
||||
repeatWrong()
|
||||
} else {
|
||||
if (store.current.index === store.chapter.length - 1) {
|
||||
if (store.current.index === store.current.words.length - 1) {
|
||||
if (store.current.wrongWords.length) {
|
||||
store.setCurrentWord(store.current.wrongWords)
|
||||
} else {
|
||||
if (store.currentDict.chapterIndex !== store.currentDict.chapters.length - 1) {
|
||||
console.log('这一章节完了')
|
||||
// emitter.emit(EventKey.openStatModal)
|
||||
emitter.emit(EventKey.openStatModal)
|
||||
} else {
|
||||
console.log('这本书完了')
|
||||
emitter.emit(EventKey.openStatModal)
|
||||
}
|
||||
} else {
|
||||
store.current.index++
|
||||
|
||||
// var msg = new SpeechSynthesisUtterance();
|
||||
// // msg.text = store.word.name
|
||||
// msg.text = 'Hawaii wildfires burn historic town of Lahaina to the ground'
|
||||
// msg.rate = 0.8;
|
||||
// msg.pitch = 1;
|
||||
// msg.lang = 'en-US';
|
||||
// window.speechSynthesis.speak(msg);
|
||||
|
||||
console.log('这个词完了')
|
||||
if (store.current.index) {
|
||||
store.current.statistics.wrongWordNumber = store.current.index - store.current.wrongWords.length
|
||||
store.current.statistics.correctRate = Math.trunc(((store.current.index - store.current.wrongWords.length) / (store.current.index)) * 100)
|
||||
} else {
|
||||
store.current.statistics.correctRate = -1
|
||||
store.current.statistics.wrongWordNumber = -1
|
||||
}
|
||||
}
|
||||
if ([DictType.custom, DictType.inner].includes(store.current.dictType) && store.skipWordNames.includes(store.word.name)) {
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
store.current.index++
|
||||
|
||||
// var msg = new SpeechSynthesisUtterance();
|
||||
// // msg.text = store.word.name
|
||||
// msg.text = 'Hawaii wildfires burn historic town of Lahaina to the ground'
|
||||
// msg.rate = 0.8;
|
||||
// msg.pitch = 1;
|
||||
// msg.lang = 'en-US';
|
||||
// window.speechSynthesis.speak(msg);
|
||||
|
||||
console.log('这个词完了')
|
||||
}
|
||||
if ([DictType.custom, DictType.inner].includes(store.current.dictType) && store.skipWordNames.includes(store.word.name)) {
|
||||
next()
|
||||
}
|
||||
|
||||
if (store.current.index) {
|
||||
store.current.statistics.wrongWordNumber = store.current.wrongWords.length
|
||||
store.current.statistics.correctRate = Math.trunc(((store.current.index - store.current.wrongWords.length) / (store.current.index)) * 100)
|
||||
} else {
|
||||
store.current.statistics.wrongWordNumber = -1
|
||||
store.current.statistics.correctRate = -1
|
||||
}
|
||||
wrong = input = ''
|
||||
}
|
||||
|
||||
@@ -135,13 +116,13 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
wrong = ''
|
||||
playKeySound()
|
||||
} else {
|
||||
if (!store.allWrongDict.wordList.find((v: Word) => v.name === store.word.name)) {
|
||||
store.allWrongDict.wordList.push(store.word)
|
||||
if (!store.wrongWordDict.originWords.find((v: Word) => v.name === store.word.name)) {
|
||||
store.wrongWordDict.originWords.push(store.word)
|
||||
}
|
||||
if (!store.currentWrongDict.wordList.find((v: Word) => v.name === store.word.name)) {
|
||||
store.currentWrongDict.wordList.push(store.word)
|
||||
if (!store.current.wrongWords.find((v: Word) => v.name === store.word.name)) {
|
||||
store.current.wrongWords.push(store.word)
|
||||
}
|
||||
store.lastStatistics.correctRate = Math.trunc(((store.currentDict.wordIndex + 1 - store.currentWrongDict.wordList.length) / (store.currentDict.wordIndex + 1)) * 100)
|
||||
store.current.statistics.correctRate = Math.trunc(((store.current.index + 1 - store.current.wrongWords.length) / (store.current.index + 1)) * 100)
|
||||
wrong = letter
|
||||
playKeySound()
|
||||
playBeep()
|
||||
@@ -165,14 +146,14 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
}
|
||||
break
|
||||
case keyMap.Collect:
|
||||
if (!store.newWordDict.wordList.find((v: Word) => v.name === store.word.name)) {
|
||||
store.newWordDict.wordList.push(store.word)
|
||||
if (!store.newWordDict.originWords.find((v: Word) => v.name === store.word.name)) {
|
||||
store.newWordDict.originWords.push(store.word)
|
||||
}
|
||||
activeIndex = 1
|
||||
break
|
||||
case keyMap.Remove:
|
||||
if (!store.skipWordNames.includes(store.word.name)) {
|
||||
store.skipWordDict.wordList.push(store.word)
|
||||
store.skipWordDict.originWords.push(store.word)
|
||||
}
|
||||
activeIndex = 0
|
||||
next()
|
||||
@@ -194,7 +175,7 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
|
||||
const progress = $computed(() => {
|
||||
if (!store.chapter.length) return 0
|
||||
return ((store.currentDict.wordIndex / store.chapter.length) * 100)
|
||||
return ((store.current.index / store.current.words.length) * 100)
|
||||
})
|
||||
|
||||
const {toggle} = useTheme()
|
||||
@@ -203,6 +184,17 @@ function format(val: number, suffix: string = '') {
|
||||
return val === -1 ? '-' : (val + suffix)
|
||||
}
|
||||
|
||||
let speedMinute = $ref(0)
|
||||
let timer = $ref(0)
|
||||
onMounted(() => {
|
||||
timer = setInterval(() => {
|
||||
speedMinute = Math.floor((Date.now() - store.current.statistics.startDate) / 1000 / 60)
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
timer && clearInterval(timer)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -246,17 +238,27 @@ function format(val: number, suffix: string = '') {
|
||||
:show-text="false"/>
|
||||
<div class="stat">
|
||||
<div class="row">
|
||||
<div class="num">{{ store.currentDict.wordIndex }}</div>
|
||||
<div class="num">{{ speedMinute }}分钟</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">时间</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ store.current.statistics.wordNumber }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">单词总数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ store.current.index }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">输入数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ format(store.currentWrongDict.wordList.length) }}</div>
|
||||
<div class="num">{{ format(store.current.wrongWords.length) }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">错误数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ format(store.lastStatistics.correctRate, '%') }}</div>
|
||||
<div class="num">{{ format(store.current.statistics.correctRate, '%') }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">正确率</div>
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,8 @@ export const useBaseStore = defineStore('base', {
|
||||
words: [],
|
||||
index: -1,
|
||||
wrongWords: [],
|
||||
repeatNumber: -1,
|
||||
originWrongWords: [],
|
||||
repeatNumber: 0,
|
||||
statistics: {
|
||||
startDate: -1,
|
||||
endDate: -1,
|
||||
@@ -121,6 +122,14 @@ export const useBaseStore = defineStore('base', {
|
||||
ukphone: '',
|
||||
}
|
||||
},
|
||||
dictTitle(state: State) {
|
||||
let title = this.currentDict.name
|
||||
if ([DictType.inner, DictType.custom].includes(this.current.dictType)) {
|
||||
title += ` 第${this.currentDict.chapterIndex + 1}章`
|
||||
title += this.current.repeatNumber ? ' 复习错词' : ''
|
||||
}
|
||||
return title
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
@@ -129,6 +138,30 @@ export const useBaseStore = defineStore('base', {
|
||||
}
|
||||
// console.log('this/', this)
|
||||
},
|
||||
setCurrentWord(words: Word[], restart: boolean = false) {
|
||||
this.current.words = cloneDeep(words)
|
||||
if (restart) {
|
||||
this.current.repeatNumber = 0
|
||||
this.current.originWrongWords = []
|
||||
this.current.statistics = {
|
||||
startDate: Date.now(),
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
wordNumber: words.length,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
} else {
|
||||
this.current.repeatNumber++
|
||||
if (!this.current.originWrongWords.length) {
|
||||
this.current.originWrongWords = cloneDeep(this.current.wrongWords)
|
||||
}
|
||||
this.current.statistics.correctRate = -1
|
||||
this.current.statistics.wrongWordNumber = -1
|
||||
}
|
||||
this.current.index = 0
|
||||
this.current.wrongWords = []
|
||||
},
|
||||
async init() {
|
||||
// let configStr = localStorage.getItem(SaveKey)
|
||||
// if (configStr) {
|
||||
@@ -141,9 +174,9 @@ export const useBaseStore = defineStore('base', {
|
||||
this.dict.originWords = cloneDeep(v)
|
||||
this.dict.words = cloneDeep(v)
|
||||
this.dict.chapters = chunk(this.dict.originWords, this.dict.chapterWordNumber)
|
||||
this.setCurrentWord(this.chapter, true)
|
||||
})
|
||||
}
|
||||
this.dict.wordIndex = 0
|
||||
},
|
||||
async changeDict(dict: Dict, chapterIndex: number = -1, chapterWordIndex: number = -1) {
|
||||
console.log('changeDict', dict)
|
||||
|
||||
11
src/types.ts
11
src/types.ts
@@ -1,4 +1,3 @@
|
||||
|
||||
export type Word = {
|
||||
"name": string,
|
||||
"usphone": string,
|
||||
@@ -107,6 +106,15 @@ export interface Statistics {
|
||||
wrongWordNumber: number//错误数
|
||||
}
|
||||
|
||||
export const DefaultStatistics: Statistics = {
|
||||
startDate: Date.now(),
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
wordNumber: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
|
||||
export enum Sort {
|
||||
normal = 0,
|
||||
random = 1,
|
||||
@@ -124,6 +132,7 @@ export interface State {
|
||||
words: Word[],
|
||||
index: number,
|
||||
wrongWords: Word[],
|
||||
originWrongWords: Word[],
|
||||
repeatNumber: number,
|
||||
statistics: Statistics
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user