开发中
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Toolbar from "@/components/Toolbar/Toolbar.vue"
|
||||
import {watch} from "vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import {usePracticeStore} from "@/components/Practice/usePracticeStore.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";
|
||||
|
||||
const practiceStore = usePracticeStore()
|
||||
const store = useBaseStore()
|
||||
|
||||
watch(practiceStore, () => {
|
||||
if (practiceStore.inputNumber < 1) {
|
||||
@@ -18,6 +20,22 @@ watch(practiceStore, () => {
|
||||
}
|
||||
practiceStore.correctRate = 100 - Math.trunc(((practiceStore.wrongNumber) / (practiceStore.inputNumber)) * 100)
|
||||
})
|
||||
let wordData = $ref({
|
||||
words: [],
|
||||
index: -1
|
||||
})
|
||||
|
||||
watch(()=>store.load,n=>{
|
||||
if (n){
|
||||
wordData.words = store.chapter
|
||||
wordData.index = 0
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
@@ -25,7 +43,10 @@ watch(practiceStore, () => {
|
||||
<div class="practice">
|
||||
<Toolbar/>
|
||||
<TypeArticle v-if="practiceStore.type === 'article'"/>
|
||||
<TypeWord v-else/>
|
||||
<TypeWord
|
||||
:words="wordData.words"
|
||||
:index="wordData.index"
|
||||
v-else/>
|
||||
<Footer/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -42,14 +42,17 @@ let data = $ref({
|
||||
words: props.words,
|
||||
wrongWords: [],
|
||||
originWrongWords: [],
|
||||
repeatNumber: 0,
|
||||
startDate: Date.now(),
|
||||
correctRate: -1,
|
||||
})
|
||||
|
||||
watch(() => props.words, (n: Word[]) => {
|
||||
data.words = n
|
||||
data.index = n.length ? 0 : -1
|
||||
practiceStore.inputNumber = 0
|
||||
practiceStore.wrongNumber = 0
|
||||
practiceStore.repeatNumber = 0
|
||||
practiceStore.total = n.length
|
||||
practiceStore.wrongWords = []
|
||||
practiceStore.startDate = Date.now()
|
||||
})
|
||||
|
||||
|
||||
@@ -87,7 +90,6 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
useEventListener('keydown', onKeyDown)
|
||||
useEventListener('keyup', onKeyUp)
|
||||
|
||||
@@ -99,21 +101,25 @@ function next() {
|
||||
data.originWrongWords = cloneDeep(data.wrongWords)
|
||||
}
|
||||
data.index = 0
|
||||
data.repeatNumber++
|
||||
practiceStore.total = data.words.length
|
||||
practiceStore.inputNumber = 0
|
||||
practiceStore.wrongNumber = 0
|
||||
practiceStore.repeatNumber++
|
||||
data.wrongWords = []
|
||||
} else {
|
||||
console.log('这本书完了')
|
||||
console.log('这章节完了')
|
||||
practiceStore.wrongWords = cloneDeep(data.originWrongWords)
|
||||
emitter.emit(EventKey.openStatModal)
|
||||
}
|
||||
} else {
|
||||
data.index++
|
||||
practiceStore.inputNumber++
|
||||
console.log('这个词完了')
|
||||
if ([DictType.customDict, DictType.innerDict].includes(store.current.dictType)
|
||||
&& store.skipWordNames.includes(word.name.toLowerCase())) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
wrong = input = ''
|
||||
}
|
||||
|
||||
@@ -137,6 +143,7 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
}
|
||||
if (!data.wrongWords.find((v: Word) => v.name.toLowerCase() === word.name.toLowerCase())) {
|
||||
data.wrongWords.push(word)
|
||||
practiceStore.wrongNumber++
|
||||
}
|
||||
wrong = letter
|
||||
playKeySound()
|
||||
@@ -160,7 +167,7 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
}
|
||||
break
|
||||
case ShortKeyMap.Collect:
|
||||
if (!store.newWordDict.originWords.find((v: Word) => v.name === word.name)) {
|
||||
if (!store.newWordDict.originWords.find((v: Word) => v.name.toLowerCase() === word.name.toLowerCase())) {
|
||||
store.newWordDict.originWords.push(word)
|
||||
store.newWordDict.words.push(word)
|
||||
store.newWordDict.chapterWords = [store.newWordDict.words]
|
||||
@@ -168,7 +175,7 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
activeIndex = 1
|
||||
break
|
||||
case ShortKeyMap.Remove:
|
||||
if (!store.skipWordNames.includes(word.name)) {
|
||||
if (!store.skipWordNames.includes(word.name.toLowerCase())) {
|
||||
store.skipWordDict.originWords.push(word)
|
||||
store.skipWordDict.words.push(word)
|
||||
store.skipWordDict.chapterWords = [store.skipWordDict.words]
|
||||
|
||||
@@ -20,9 +20,9 @@ export const usePracticeStore = defineStore('practice', {
|
||||
repeatNumber: 0,
|
||||
startDate: Date.now(),
|
||||
correctRate: -1,
|
||||
total: -1,
|
||||
inputNumber: -1,
|
||||
wrongNumber: -1,
|
||||
total: 0,
|
||||
inputNumber: 0,
|
||||
wrongNumber: 0,
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -4,223 +4,225 @@ import {chunk, cloneDeep} from "lodash";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
|
||||
export const useBaseStore = defineStore('base', {
|
||||
state: (): State => {
|
||||
return {
|
||||
newWordDict: {
|
||||
name: '生词本',
|
||||
sort: Sort.normal,
|
||||
type: DictType.newDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '',
|
||||
},
|
||||
skipWordDict: {
|
||||
name: '简单词',
|
||||
sort: Sort.normal,
|
||||
type: DictType.skipDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '',
|
||||
},
|
||||
wrongWordDict: {
|
||||
name: '错词本',
|
||||
sort: Sort.normal,
|
||||
type: DictType.wrongDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '',
|
||||
},
|
||||
dict: {
|
||||
name: '新概念英语-2',
|
||||
sort: Sort.normal,
|
||||
type: DictType.innerDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '/dicts/NCE_2.json',
|
||||
},
|
||||
oldDicts: [],
|
||||
current: {
|
||||
dictType: DictType.innerDict,
|
||||
words: [],
|
||||
index: -1,
|
||||
wrongWords: [],
|
||||
originWrongWords: [],
|
||||
repeatNumber: 0,
|
||||
statistics: {
|
||||
startDate: -1,
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
wordNumber: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
},
|
||||
sideIsOpen: false,
|
||||
isDictation: true,
|
||||
setting: {
|
||||
showToolbar: true,
|
||||
show: false,
|
||||
value1: false,
|
||||
value2: 50,
|
||||
value3: 1,
|
||||
value4: false,
|
||||
},
|
||||
simpleWords: [
|
||||
'a', 'an', 'of', 'and',
|
||||
'i', 'my', 'you', 'your',
|
||||
'me', 'am', 'is', 'do', 'are',
|
||||
'what', 'who', 'where', 'how', 'no', 'yes',
|
||||
'not', 'did', 'were', 'can', 'could', 'it',
|
||||
'the', 'to'
|
||||
],
|
||||
theme: 'auto'
|
||||
state: (): State => {
|
||||
return {
|
||||
newWordDict: {
|
||||
name: '生词本',
|
||||
sort: Sort.normal,
|
||||
type: DictType.newDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '',
|
||||
},
|
||||
skipWordDict: {
|
||||
name: '简单词',
|
||||
sort: Sort.normal,
|
||||
type: DictType.skipDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '',
|
||||
},
|
||||
wrongWordDict: {
|
||||
name: '错词本',
|
||||
sort: Sort.normal,
|
||||
type: DictType.wrongDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '',
|
||||
},
|
||||
dict: {
|
||||
name: '新概念英语-2',
|
||||
sort: Sort.normal,
|
||||
type: DictType.innerDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
url: '/dicts/NCE_2.json',
|
||||
},
|
||||
oldDicts: [],
|
||||
current: {
|
||||
dictType: DictType.innerDict,
|
||||
words: [],
|
||||
index: -1,
|
||||
wrongWords: [],
|
||||
originWrongWords: [],
|
||||
repeatNumber: 0,
|
||||
statistics: {
|
||||
startDate: -1,
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
wordNumber: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
},
|
||||
sideIsOpen: false,
|
||||
isDictation: true,
|
||||
setting: {
|
||||
showToolbar: true,
|
||||
show: false,
|
||||
value1: false,
|
||||
value2: 50,
|
||||
value3: 1,
|
||||
value4: false,
|
||||
},
|
||||
simpleWords: [
|
||||
'a', 'an', 'of', 'and',
|
||||
'i', 'my', 'you', 'your',
|
||||
'me', 'am', 'is', 'do', 'are',
|
||||
'what', 'who', 'where', 'how', 'no', 'yes',
|
||||
'not', 'did', 'were', 'can', 'could', 'it',
|
||||
'the', 'to'
|
||||
],
|
||||
theme: 'auto',
|
||||
load: false
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
skipWordNames: (state: State) => {
|
||||
return state.skipWordDict.originWords.map(v => v.name.toLowerCase())
|
||||
},
|
||||
getters: {
|
||||
skipWordNames: (state: State) => {
|
||||
return state.skipWordDict.originWords.map(v => v.name.toLowerCase())
|
||||
},
|
||||
skipWordNamesWithSimpleWords: (state: State) => {
|
||||
return state.skipWordDict.originWords.map(v => v.name.toLowerCase()).concat(state.simpleWords)
|
||||
},
|
||||
currentDict(state: State): Dict {
|
||||
switch (state.current.dictType) {
|
||||
case DictType.newDict:
|
||||
return state.newWordDict
|
||||
case DictType.skipDict:
|
||||
return state.skipWordDict
|
||||
case DictType.wrongDict:
|
||||
return state.wrongWordDict
|
||||
case DictType.innerDict:
|
||||
case DictType.customDict:
|
||||
return state.dict
|
||||
}
|
||||
},
|
||||
wordIndex(state: State): number {
|
||||
return this.currentDict.wordIndex
|
||||
},
|
||||
chapter(state: State): Word[] {
|
||||
return this.currentDict.chapterWords[this.currentDict.chapterIndex] ?? []
|
||||
},
|
||||
word(state: State): Word {
|
||||
return state.current.words[state.current.index] ?? {
|
||||
trans: [],
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
}
|
||||
},
|
||||
dictTitle(state: State) {
|
||||
let title = this.currentDict.name
|
||||
if ([DictType.innerDict, DictType.customDict].includes(this.current.dictType)) {
|
||||
title += ` 第${this.currentDict.chapterIndex + 1}章`
|
||||
title += this.current.repeatNumber ? ' 复习错词' : ''
|
||||
}
|
||||
return title
|
||||
skipWordNamesWithSimpleWords: (state: State) => {
|
||||
return state.skipWordDict.originWords.map(v => v.name.toLowerCase()).concat(state.simpleWords)
|
||||
},
|
||||
currentDict(state: State): Dict {
|
||||
switch (state.current.dictType) {
|
||||
case DictType.newDict:
|
||||
return state.newWordDict
|
||||
case DictType.skipDict:
|
||||
return state.skipWordDict
|
||||
case DictType.wrongDict:
|
||||
return state.wrongWordDict
|
||||
case DictType.innerDict:
|
||||
case DictType.customDict:
|
||||
return state.dict
|
||||
}
|
||||
},
|
||||
wordIndex(state: State): number {
|
||||
return this.currentDict.wordIndex
|
||||
},
|
||||
chapter(state: State): Word[] {
|
||||
return this.currentDict.chapterWords[this.currentDict.chapterIndex] ?? []
|
||||
},
|
||||
word(state: State): Word {
|
||||
return state.current.words[state.current.index] ?? {
|
||||
trans: [],
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
}
|
||||
},
|
||||
dictTitle(state: State) {
|
||||
let title = this.currentDict.name
|
||||
if ([DictType.innerDict, DictType.customDict].includes(this.current.dictType)) {
|
||||
title += ` 第${this.currentDict.chapterIndex + 1}章`
|
||||
title += this.current.repeatNumber ? ' 复习错词' : ''
|
||||
}
|
||||
return title
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
this[key] = value
|
||||
}
|
||||
// console.log('this/', this)
|
||||
},
|
||||
setCurrentWord(words: Word[], restart: boolean = false, index: number = 0) {
|
||||
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,
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
this[key] = value
|
||||
}
|
||||
// console.log('this/', this)
|
||||
},
|
||||
setCurrentWord(words: Word[], restart: boolean = false, index: number = 0) {
|
||||
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 = index
|
||||
this.current.wrongWords = []
|
||||
},
|
||||
async init() {
|
||||
// let configStr = localStorage.getItem(SaveKey)
|
||||
// if (configStr) {
|
||||
// let obj: Config = JSON.parse(configStr)
|
||||
// this.setState(obj)
|
||||
// }
|
||||
if (this.current.dictType === DictType.innerDict) {
|
||||
let r = await fetch(`/public/${this.dict.url}`)
|
||||
r.json().then(v => {
|
||||
this.dict.originWords = cloneDeep(v)
|
||||
this.dict.words = cloneDeep(v)
|
||||
this.dict.chapters = chunk(this.dict.words, this.dict.chapterWordNumber)
|
||||
this.setCurrentWord(this.chapter, true)
|
||||
})
|
||||
}
|
||||
},
|
||||
saveStatistics() {
|
||||
let currentStat = cloneDeep(this.current.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)
|
||||
}
|
||||
return currentStat
|
||||
},
|
||||
async changeDict(dict: Dict, chapterIndex: number = dict.chapterIndex, chapterWordIndex: number = dict.chapterWordNumber) {
|
||||
this.saveStatistics()
|
||||
console.log('changeDict', cloneDeep(dict), chapterIndex, chapterWordIndex)
|
||||
this.current.dictType = dict.type
|
||||
if ([DictType.newDict,
|
||||
DictType.skipDict,
|
||||
DictType.wrongDict].includes(dict.type)) {
|
||||
this[dict.type].chapterIndex = chapterIndex
|
||||
this[dict.type].chapterWordIndex = chapterWordIndex
|
||||
} else {
|
||||
this.dict = cloneDeep(dict)
|
||||
if (dict.originWords.length) {
|
||||
let r = await fetch(`/public/${this.dict.url}`)
|
||||
let v = await r.json()
|
||||
this.dict.originWords = cloneDeep(v)
|
||||
this.dict.words = cloneDeep(v)
|
||||
this.dict.chapters = chunk(this.dict.words, this.dict.chapterWordNumber)
|
||||
}
|
||||
this.dict.chapterIndex = chapterIndex
|
||||
this.dict.chapterWordIndex = chapterWordIndex
|
||||
}
|
||||
this.setCurrentWord(this.chapter, true, chapterWordIndex)
|
||||
emitter.emit(EventKey.resetWord)
|
||||
} 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 = index
|
||||
this.current.wrongWords = []
|
||||
},
|
||||
async init() {
|
||||
// let configStr = localStorage.getItem(SaveKey)
|
||||
// if (configStr) {
|
||||
// let obj: Config = JSON.parse(configStr)
|
||||
// this.setState(obj)
|
||||
// }
|
||||
if (this.current.dictType === DictType.innerDict) {
|
||||
let r = await fetch(`/public/${this.dict.url}`)
|
||||
r.json().then(v => {
|
||||
this.dict.originWords = cloneDeep(v)
|
||||
this.dict.words = cloneDeep(v)
|
||||
this.dict.chapterWords = chunk(this.dict.words, this.dict.chapterWordNumber)
|
||||
this.setCurrentWord(this.chapter, true)
|
||||
this.load = true
|
||||
})
|
||||
}
|
||||
},
|
||||
saveStatistics() {
|
||||
let currentStat = cloneDeep(this.current.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)
|
||||
}
|
||||
return currentStat
|
||||
},
|
||||
async changeDict(dict: Dict, chapterIndex: number = dict.chapterIndex, chapterWordIndex: number = dict.chapterWordNumber) {
|
||||
this.saveStatistics()
|
||||
console.log('changeDict', cloneDeep(dict), chapterIndex, chapterWordIndex)
|
||||
this.current.dictType = dict.type
|
||||
if ([DictType.newDict,
|
||||
DictType.skipDict,
|
||||
DictType.wrongDict].includes(dict.type)) {
|
||||
this[dict.type].chapterIndex = chapterIndex
|
||||
this[dict.type].chapterWordIndex = chapterWordIndex
|
||||
} else {
|
||||
this.dict = cloneDeep(dict)
|
||||
if (dict.originWords.length) {
|
||||
let r = await fetch(`/public/${this.dict.url}`)
|
||||
let v = await r.json()
|
||||
this.dict.originWords = cloneDeep(v)
|
||||
this.dict.words = cloneDeep(v)
|
||||
this.dict.chapters = chunk(this.dict.words, this.dict.chapterWordNumber)
|
||||
}
|
||||
this.dict.chapterIndex = chapterIndex
|
||||
this.dict.chapterWordIndex = chapterWordIndex
|
||||
}
|
||||
this.setCurrentWord(this.chapter, true, chapterWordIndex)
|
||||
emitter.emit(EventKey.resetWord)
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -173,7 +173,8 @@ export interface State {
|
||||
value2: number,
|
||||
value3: number,
|
||||
value4: boolean,
|
||||
}
|
||||
},
|
||||
load:boolean
|
||||
}
|
||||
|
||||
export const ShortKeyMap = {
|
||||
|
||||
Reference in New Issue
Block a user