save
This commit is contained in:
@@ -4,7 +4,7 @@ import {$computed, $ref} from "vue/macros"
|
||||
import {onMounted, onUnmounted} from "vue"
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import Tooltip from "@/components/Tooltip.vue"
|
||||
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts";
|
||||
import {usePracticeStore} from "@/components/Practice/practice.ts";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
|
||||
|
||||
@@ -2,16 +2,19 @@
|
||||
|
||||
import Toolbar from "@/components/Toolbar/Toolbar.vue"
|
||||
import {onMounted, watch} from "vue";
|
||||
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts";
|
||||
import {usePracticeStore} from "@/components/Practice/practice.ts";
|
||||
import Footer from "@/components/Practice/Footer.vue";
|
||||
import TypeWord from "@/components/Practice/TypeWord.vue";
|
||||
import TypeArticle from "@/components/Practice/TypeArticle.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {$ref} from "vue/macros";
|
||||
import Statistics from "@/components/Practice/Statistics.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus";
|
||||
import {useSettingStore} from "@/stores/setting";
|
||||
|
||||
const practiceStore = usePracticeStore()
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
watch(practiceStore, () => {
|
||||
if (practiceStore.inputNumber < 1) {
|
||||
@@ -1135,15 +1138,36 @@ let articleData = $ref({
|
||||
|
||||
watch(() => store.load, n => {
|
||||
if (n) {
|
||||
wordData.words = store.chapter
|
||||
wordData.index = 0
|
||||
getCurrentWords()
|
||||
}
|
||||
})
|
||||
|
||||
function getCurrentWords() {
|
||||
wordData.words = store.chapter
|
||||
wordData.index = 0
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
|
||||
function write() {
|
||||
settingStore.dictation = true
|
||||
repeat()
|
||||
}
|
||||
|
||||
//TODO 需要判断是否已忽略
|
||||
function repeat() {
|
||||
getCurrentWords()
|
||||
emitter.emit(EventKey.resetWord)
|
||||
}
|
||||
|
||||
//TODO 能否下一章
|
||||
function next() {
|
||||
store.currentDict.chapterIndex++
|
||||
repeat()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -1163,7 +1187,11 @@ onMounted(() => {
|
||||
v-else/>
|
||||
<Footer/>
|
||||
</div>
|
||||
<Statistics/>
|
||||
<Statistics
|
||||
@write="write"
|
||||
@repeat="repeat"
|
||||
@next="next"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -5,58 +5,39 @@ 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 {DefaultStatistics, Statistics} from "@/types.ts";
|
||||
import {DefaultDisplayStatistics, DisplayStatistics, Statistics} from "@/types.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {Icon} from '@iconify/vue';
|
||||
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts";
|
||||
import {usePracticeStore} from "@/components/Practice/practice.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
let statModalIsOpen = $ref(false)
|
||||
let currentStat = reactive<Statistics>(cloneDeep(DefaultStatistics))
|
||||
const practiceStore = usePracticeStore()
|
||||
let currentStat = reactive<DisplayStatistics>(cloneDeep(DefaultDisplayStatistics))
|
||||
|
||||
const emit = defineEmits([
|
||||
'repeat',
|
||||
'next',
|
||||
'write'
|
||||
])
|
||||
onMounted(() => {
|
||||
emitter.on(EventKey.openStatModal, () => {
|
||||
emitter.on(EventKey.openStatModal, (stat: DisplayStatistics) => {
|
||||
statModalIsOpen = true
|
||||
let now = Date.now()
|
||||
currentStat = {
|
||||
startDate: practiceStore.startDate,
|
||||
endDate: now,
|
||||
spend: now - practiceStore.startDate,
|
||||
total: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
currentStat = stat
|
||||
})
|
||||
})
|
||||
|
||||
function write() {
|
||||
settingStore.dictation = true
|
||||
repeat()
|
||||
}
|
||||
|
||||
//TODO 需要判断是否已忽略
|
||||
function repeat() {
|
||||
console.log(store.chapter)
|
||||
store.setCurrentWord(store.chapter, true)
|
||||
function options(emitType: string) {
|
||||
statModalIsOpen = false
|
||||
emitter.emit(EventKey.resetWord)
|
||||
}
|
||||
|
||||
//TODO 能否下一章
|
||||
function next() {
|
||||
store.currentDict.chapterIndex++
|
||||
repeat()
|
||||
emit(emitType)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal v-model="statModalIsOpen" @close="next">
|
||||
<Modal v-model="statModalIsOpen" @close="options('next')">
|
||||
<div class="statistics">
|
||||
<header>
|
||||
<div class="title">{{ store.currentDict.name }}</div>
|
||||
@@ -81,11 +62,11 @@ function next() {
|
||||
<div class="result">
|
||||
<div class="wrong-words-wrapper">
|
||||
<div class="wrong-words">
|
||||
<div class="word" v-for="i in store.current.originWrongWords">{{ i.name }}</div>
|
||||
<div class="word" v-for="i in currentStat.wrongWords">{{ i.name }}</div>
|
||||
<!-- <div class="word" v-for="i in 100">{{ i }}</div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="notice" v-if="!store.current.originWrongWords.length">
|
||||
<div class="notice" v-if="!currentStat.wrongWords.length">
|
||||
<!-- <div class="notice">-->
|
||||
<Icon class="hvr-grow pointer" icon="flat-color-icons:like" width="20" color="#929596"/>
|
||||
表现不错,全对了!
|
||||
@@ -101,13 +82,13 @@ function next() {
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<BaseButton keyboard="Ctrl + Enter" @click="write">
|
||||
<BaseButton keyboard="Ctrl + Enter" @click="options('write')">
|
||||
默写本章
|
||||
</BaseButton>
|
||||
<BaseButton keyboard="Alt + Enter" @click="repeat">
|
||||
<BaseButton keyboard="Alt + Enter" @click="options('repeat')">
|
||||
重复本章
|
||||
</BaseButton>
|
||||
<BaseButton keyboard="Tab" @click="next">
|
||||
<BaseButton keyboard="Tab" @click="options('next')">
|
||||
下一章
|
||||
</BaseButton>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import {computed, nextTick, watchEffect} from "vue"
|
||||
import {$ref} from "vue/macros";
|
||||
import {Article, ArticleWord, ShortKeyMap, Word} from "@/types";
|
||||
import {useBaseStore} from "@/stores/base";
|
||||
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts";
|
||||
import {usePracticeStore} from "@/components/Practice/practice.ts";
|
||||
import TypeWord from "@/components/Practice/TypeWord.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
import {onMounted, watchEffect} from "vue"
|
||||
import {$computed, $ref} from "vue/macros"
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import {DictType, ShortKeyMap, Word} from "../../types";
|
||||
import {DictType, DisplayStatistics, ShortKeyMap, Statistics, Word} from "../../types";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
import {cloneDeep} from "lodash-es"
|
||||
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts"
|
||||
import {usePracticeStore} from "@/components/Practice/practice.ts"
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {useEventListener} from "@/hooks/event.ts";
|
||||
@@ -81,6 +81,7 @@ useEventListener('keyup', onKeyUp)
|
||||
function next() {
|
||||
if (data.index === data.words.length - 1) {
|
||||
if (data.wrongWords.length) {
|
||||
console.log('当前背完了,但还有错词')
|
||||
data.words = cloneDeep(data.wrongWords)
|
||||
if (!data.originWrongWords.length) {
|
||||
data.originWrongWords = cloneDeep(data.wrongWords)
|
||||
@@ -93,16 +94,18 @@ function next() {
|
||||
data.wrongWords = []
|
||||
} else {
|
||||
console.log('这章节完了')
|
||||
|
||||
let now = Date.now()
|
||||
emitter.emit(EventKey.openStatModal, {
|
||||
let stat: DisplayStatistics = {
|
||||
startDate: practiceStore.startDate,
|
||||
endDate: now,
|
||||
spend: now - practiceStore.startDate,
|
||||
total: props.words.length,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: data.originWrongWords.length,
|
||||
})
|
||||
wrongWords: data.originWrongWords,
|
||||
}
|
||||
stat.correctRate = 100 - Math.trunc(((stat.wrongWordNumber) / (stat.total)) * 100)
|
||||
emitter.emit(EventKey.openStatModal, stat)
|
||||
}
|
||||
} else {
|
||||
data.index++
|
||||
@@ -203,13 +206,13 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
<template>
|
||||
<div class="type-word">
|
||||
<div class="translate"
|
||||
:style="{fontSize: settingStore.foreignLanguageFontSize +'rem'}"
|
||||
:style="{fontSize: settingStore.fontSize.wordTranslateFontSize +'rem'}"
|
||||
>{{ word.trans.join(';') }}
|
||||
</div>
|
||||
<div class="word-wrapper">
|
||||
<div class="word"
|
||||
:class="wrong && 'is-wrong'"
|
||||
:style="{fontSize: settingStore.translateLanguageFontSize +'rem'}"
|
||||
:style="{fontSize: settingStore.fontSize.wordForeignFontSize +'rem'}"
|
||||
>
|
||||
<span class="input" v-if="input">{{ input }}</span>
|
||||
<span class="wrong" v-if="wrong">{{ wrong }}</span>
|
||||
|
||||
@@ -15,7 +15,8 @@ export interface PracticeState {
|
||||
export const usePracticeStore = defineStore('practice', {
|
||||
state: (): PracticeState => {
|
||||
return {
|
||||
type: 'article',
|
||||
// type: 'article',
|
||||
type: 'word',
|
||||
wrongWords: [],
|
||||
repeatNumber: 0,
|
||||
startDate: Date.now(),
|
||||
@@ -200,8 +200,8 @@ useWatchAllSound()
|
||||
<el-slider
|
||||
:min="10"
|
||||
:max="100"
|
||||
v-model="settingStore.foreignLanguageFontSize"/>
|
||||
<span>{{ settingStore.foreignLanguageFontSize }}</span>
|
||||
v-model="settingStore.fontSize.wordForeignFontSize"/>
|
||||
<span>{{ settingStore.fontSize.wordForeignFontSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -210,8 +210,8 @@ useWatchAllSound()
|
||||
<el-slider
|
||||
:min="10"
|
||||
:max="100"
|
||||
v-model="settingStore.translateLanguageFontSize"/>
|
||||
<span>{{ settingStore.translateLanguageFontSize }}</span>
|
||||
v-model="settingStore.fontSize.wordTranslateFontSize"/>
|
||||
<span>{{ settingStore.fontSize.wordTranslateFontSize }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -185,16 +185,9 @@ export const useBaseStore = defineStore('base', {
|
||||
}
|
||||
},
|
||||
saveStatistics(statistics: Statistics) {
|
||||
let currentStat = cloneDeep(statistics)
|
||||
currentStat.endDate = Date.now()
|
||||
currentStat.spend = Date.now() - currentStat.startDate
|
||||
currentStat.wrongWordNumber = this.current.originWrongWords.length
|
||||
currentStat.correctRate = 100 - Math.trunc((currentStat.wrongWordNumber / currentStat.wordNumber) * 100)
|
||||
// console.log(cloneDeep(currentStat))
|
||||
if (currentStat.spend > 1000 * 10) {
|
||||
this.currentDict.statistics.push(currentStat)
|
||||
if (statistics.spend > 1000 * 10) {
|
||||
this.currentDict.statistics.push(statistics)
|
||||
}
|
||||
return currentStat
|
||||
},
|
||||
async changeDict(dict: Dict, chapterIndex: number = dict.chapterIndex, chapterWordIndex: number = dict.chapterWordNumber) {
|
||||
this.saveStatistics()
|
||||
|
||||
@@ -23,8 +23,12 @@ export interface SettingState {
|
||||
ignoreCase: boolean
|
||||
allowWordTip: boolean
|
||||
waitTimeForChangeWord: number
|
||||
foreignLanguageFontSize: number,
|
||||
translateLanguageFontSize: number,
|
||||
fontSize: {
|
||||
articleForeignFontSize: number,
|
||||
articleTranslateFontSize: number,
|
||||
wordForeignFontSize: number,
|
||||
wordTranslateFontSize: number,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -53,8 +57,12 @@ export const useSettingStore = defineStore('setting', {
|
||||
showNearWord: true,
|
||||
ignoreCase: true,
|
||||
allowWordTip: true,
|
||||
foreignLanguageFontSize: 48,
|
||||
translateLanguageFontSize: 20,
|
||||
fontSize: {
|
||||
articleForeignFontSize: 48,
|
||||
articleTranslateFontSize: 20,
|
||||
wordForeignFontSize: 38,
|
||||
wordTranslateFontSize: 20,
|
||||
},
|
||||
waitTimeForChangeWord: 300,
|
||||
|
||||
}
|
||||
|
||||
@@ -147,17 +147,22 @@ export interface Statistics {
|
||||
endDate: number//结束日期
|
||||
spend: number,//花费时间
|
||||
total: number//单词数量
|
||||
correctRate: number//正确率
|
||||
wrongWordNumber: number//错误数
|
||||
correctRate: number//正确率
|
||||
}
|
||||
|
||||
export const DefaultStatistics: Statistics = {
|
||||
export interface DisplayStatistics extends Statistics {
|
||||
wrongWords: Word[]
|
||||
}
|
||||
|
||||
export const DefaultDisplayStatistics: DisplayStatistics = {
|
||||
startDate: Date.now(),
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
total: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
wrongWords: [],
|
||||
}
|
||||
|
||||
export enum Sort {
|
||||
|
||||
Reference in New Issue
Block a user