save
This commit is contained in:
9141
pnpm-lock.yaml
generated
9141
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
import {Article, Dict, DictType, Word} from "@/types.ts";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {chunk, cloneDeep} from "lodash-es";
|
||||
import {chunk, cloneDeep, shuffle} from "lodash-es";
|
||||
import {isArticle} from "@/hooks/article.ts";
|
||||
import {nanoid} from "nanoid";
|
||||
|
||||
@@ -109,24 +109,60 @@ export function syncMyDictList(dict: Dict, isCustom = true) {
|
||||
}
|
||||
|
||||
export function getCurrentStudyWord() {
|
||||
console.time()
|
||||
const store = useBaseStore()
|
||||
let data = {new: [], review: []}
|
||||
let data = {new: [], review: [], write: []}
|
||||
let c = store.currentStudy.word
|
||||
let dict = store.currentStudyWordDict;
|
||||
if (dict.words?.length) {
|
||||
for (let i = c.lastLearnIndex; i < dict.words.length; i++) {
|
||||
if (data.new.length >= c.perDayStudyNumber) break
|
||||
let item = dict.words[i]
|
||||
if (!store.skipWordNames.includes(item.word.toLowerCase())) {
|
||||
if (!store.simple2.map(v => v.word.toLowerCase()).includes(item.word.toLowerCase())) {
|
||||
data.new.push(item)
|
||||
}
|
||||
}
|
||||
if (dict.statistics.length) {
|
||||
let stat = dict.statistics.reverse()
|
||||
stat.slice(0, 1).map(({startIndex, endIndex}) => {
|
||||
let list = dict.words.splice(startIndex, endIndex)
|
||||
})
|
||||
|
||||
const getList = (startIndex, endIndex) => {
|
||||
if (startIndex < 0) return []
|
||||
return dict.words.slice(startIndex, endIndex)
|
||||
}
|
||||
|
||||
let s = c.lastLearnIndex - c.perDayStudyNumber
|
||||
let e = c.lastLearnIndex
|
||||
//取上一次学习的单词用于复习
|
||||
let list = getList(s, e)
|
||||
list.map(item => {
|
||||
if (!store.master.map(v => v.word.toLowerCase()).includes(item.word.toLowerCase())) {
|
||||
data.review.push(item)
|
||||
}
|
||||
})
|
||||
data.review = shuffle(data.review)
|
||||
|
||||
//取前天至再往前数3天的单词,用于默写,
|
||||
Array.from({length: 4}).map((_, j) => {
|
||||
e = s
|
||||
s -= c.perDayStudyNumber
|
||||
list = getList(s, e)
|
||||
let d = []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (j === 3) {
|
||||
if (d.length >= c.perDayStudyNumber - data.write.length) break
|
||||
} else {
|
||||
if (d.length >= Math.floor(c.perDayStudyNumber / 4)) break
|
||||
}
|
||||
let item = list[i]
|
||||
if (!store.master.map(v => v.word.toLowerCase()).includes(item.word.toLowerCase())) {
|
||||
d.push(item)
|
||||
}
|
||||
}
|
||||
data.write = data.write.concat(d)
|
||||
})
|
||||
|
||||
data.write = shuffle(data.write)
|
||||
}
|
||||
|
||||
console.timeEnd()
|
||||
console.log('data', data)
|
||||
return data
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export function useStartKeyboardEventListener() {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
let [k, v] = list[i]
|
||||
if (v === shortcutKey) {
|
||||
console.log('快捷键', k)
|
||||
// console.log('快捷键', k)
|
||||
shortcutEvent = k
|
||||
break
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ let show = $ref(false)
|
||||
}
|
||||
|
||||
.aside {
|
||||
background: white;
|
||||
background: var(--color-second-bg);
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: 0;
|
||||
|
||||
@@ -21,14 +21,20 @@ let open = $ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
emitter.on(EventKey.openStatModal, () => {
|
||||
let data = {
|
||||
startIndex: store.sword.lastLearnIndex,
|
||||
endIndex: store.sword.lastLearnIndex + store.sword.perDayStudyNumber,
|
||||
speed: statStore.speed,
|
||||
startDate: statStore.startDate,
|
||||
}
|
||||
store.sword.lastLearnIndex = data.endIndex
|
||||
store.currentStudyWordDict.statistics.push(data as any)
|
||||
store.currentStudyWordDict.statistics.sort((a, b) => a.startDate - b.startDate)
|
||||
|
||||
console.log('staa', JSON.parse(JSON.stringify(store.currentStudyWordDict.statistics)))
|
||||
open = true
|
||||
})
|
||||
|
||||
let data = cloneDeep(statStore)
|
||||
delete data.step
|
||||
delete data.correctRate
|
||||
store.currentStudyWordDict.statistics.push(data as any)
|
||||
|
||||
const close = () => {
|
||||
open = false
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ interface IProps {
|
||||
data: {
|
||||
new: any[],
|
||||
review: any[],
|
||||
write: any[],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +32,7 @@ const props = withDefaults(defineProps<IProps>(), {
|
||||
data: {
|
||||
new: [],
|
||||
review: [],
|
||||
write: [],
|
||||
}
|
||||
})
|
||||
|
||||
@@ -43,7 +45,7 @@ const emit = defineEmits<{
|
||||
const typingRef: any = $ref()
|
||||
const store = useBaseStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const statisticsStore = usePracticeStore()
|
||||
const statStore = usePracticeStore()
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const {
|
||||
@@ -69,14 +71,14 @@ watch(() => props.data, () => {
|
||||
current.wrongWords = []
|
||||
allWrongWords = []
|
||||
|
||||
statisticsStore.step = 0
|
||||
statisticsStore.startDate = Date.now()
|
||||
statisticsStore.correctRate = -1
|
||||
statisticsStore.inputWordNumber = 0
|
||||
statisticsStore.wrongWordNumber = 0
|
||||
statisticsStore.total = props.data.review.concat(props.data.new).length
|
||||
statisticsStore.newWordNumber = props.data.new.length
|
||||
statisticsStore.index = 0
|
||||
statStore.step = 0
|
||||
statStore.startDate = Date.now()
|
||||
statStore.correctRate = -1
|
||||
statStore.inputWordNumber = 0
|
||||
statStore.wrongWordNumber = 0
|
||||
statStore.total = props.data.review.concat(props.data.new).length
|
||||
statStore.newWordNumber = props.data.new.length
|
||||
statStore.index = 0
|
||||
}, {immediate: true, deep: true})
|
||||
|
||||
const word = $computed(() => {
|
||||
@@ -99,23 +101,37 @@ function next(isTyping: boolean = true) {
|
||||
current.index = 0
|
||||
current.wrongWords = []
|
||||
} else {
|
||||
console.log('学完了,没错词', statisticsStore.total)
|
||||
isTyping && statisticsStore.inputWordNumber++
|
||||
statisticsStore.speed = Date.now() - statisticsStore.startDate
|
||||
if (statisticsStore.step) {
|
||||
console.log('学完了,没错词', statStore.total, statStore.step,current.index,current.words)
|
||||
isTyping && statStore.inputWordNumber++
|
||||
statStore.speed = Date.now() - statStore.startDate
|
||||
|
||||
if (statStore.step === 2) {
|
||||
emitter.emit(EventKey.openStatModal, {})
|
||||
// emit('complete', {})
|
||||
} else {
|
||||
}
|
||||
|
||||
if (statStore.step === 1) {
|
||||
settingStore.dictation = true
|
||||
statisticsStore.step++
|
||||
current.words = shuffle(props.data.review.concat(props.data.new))
|
||||
current.words = props.data.write.concat(props.data.new).concat(props.data.review)
|
||||
statStore.step++
|
||||
current.index = 0
|
||||
}
|
||||
|
||||
if (statStore.step === 0) {
|
||||
statStore.step++
|
||||
if (props.data.review.length) {
|
||||
current.words = props.data.review
|
||||
settingStore.dictation = false
|
||||
current.index = 0
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current.index++
|
||||
isTyping && statisticsStore.inputWordNumber++
|
||||
console.log('这个词完了')
|
||||
isTyping && statStore.inputWordNumber++
|
||||
// console.log('这个词完了')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +144,7 @@ function wordWrong() {
|
||||
}
|
||||
if (!allWrongWords.find((v: Word) => v.word.toLowerCase() === word.word.toLowerCase())) {
|
||||
allWrongWords.push(word)
|
||||
statisticsStore.wrongWordNumber++
|
||||
statStore.wrongWordNumber++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,8 +280,10 @@ onUnmounted(() => {
|
||||
>
|
||||
<div class="list-header">
|
||||
<div>
|
||||
{{ statisticsStore.step ? '复习' : '学习'}}
|
||||
{{ current.words.length }}个单词</div>
|
||||
{{ statStore.step }}
|
||||
{{ statStore.step ? '复习' : '学习' }}
|
||||
{{ current.words.length }}个单词
|
||||
</div>
|
||||
<div style="position:relative;"
|
||||
@click.stop="null">
|
||||
<BaseIcon
|
||||
|
||||
@@ -18,24 +18,23 @@ import TypingWord from "@/pages/pc/practice/practice-word/TypingWord.vue";
|
||||
import {getCurrentStudyWord, syncMyDictList} from "@/hooks/dict.ts";
|
||||
import {cloneDeep, shuffle} from "lodash-es";
|
||||
|
||||
const statisticsStore = usePracticeStore()
|
||||
const statStore = usePracticeStore()
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const {toggleTheme} = useTheme()
|
||||
|
||||
watch(statisticsStore, () => {
|
||||
if (statisticsStore.inputWordNumber < 1) {
|
||||
return statisticsStore.correctRate = -1
|
||||
watch(statStore, () => {
|
||||
if (statStore.inputWordNumber < 1) {
|
||||
return statStore.correctRate = -1
|
||||
}
|
||||
if (statisticsStore.wrongWordNumber > statisticsStore.inputWordNumber) {
|
||||
return statisticsStore.correctRate = 0
|
||||
if (statStore.wrongWordNumber > statStore.inputWordNumber) {
|
||||
return statStore.correctRate = 0
|
||||
}
|
||||
statisticsStore.correctRate = 100 - Math.trunc(((statisticsStore.wrongWordNumber) / (statisticsStore.inputWordNumber)) * 100)
|
||||
statStore.correctRate = 100 - Math.trunc(((statStore.wrongWordNumber) / (statStore.inputWordNumber)) * 100)
|
||||
})
|
||||
|
||||
function next() {
|
||||
store.currentStudy.word.lastLearnIndex = store.currentStudy.word.lastLearnIndex + store.currentStudy.word.perDayStudyNumber
|
||||
emitter.emit(EventKey.resetWord)
|
||||
getCurrentPractice()
|
||||
}
|
||||
@@ -104,7 +103,9 @@ onUnmounted(() => {
|
||||
|
||||
onMounted(() => {
|
||||
settingStore.dictation = false
|
||||
data = runtimeStore.routeData
|
||||
if (runtimeStore.routeData) {
|
||||
data = runtimeStore.routeData
|
||||
}
|
||||
emitter.on(EventKey.changeDict, getCurrentPractice)
|
||||
})
|
||||
|
||||
|
||||
@@ -10,8 +10,11 @@ import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import {getDefaultDict} from "@/types.ts";
|
||||
import {onMounted} from "vue";
|
||||
import {getCurrentStudyWord} from "@/hooks/dict.ts";
|
||||
import {c} from "vite/dist/node/types.d-aGj9QkWt";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
|
||||
const store = useBaseStore()
|
||||
const statStore = usePracticeStore()
|
||||
const router = useRouter()
|
||||
const {nav} = useNav()
|
||||
|
||||
@@ -28,13 +31,18 @@ const otherWordDictList = $computed(() => {
|
||||
|
||||
let currentStudy = $ref({
|
||||
new: [],
|
||||
review: []
|
||||
review: [],
|
||||
write: []
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
currentStudy = getCurrentStudyWord()
|
||||
})
|
||||
|
||||
function study(){
|
||||
nav('study-word',{},currentStudy)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -92,11 +100,17 @@ onMounted(() => {
|
||||
<div class="text-4xl font-bold">{{ currentStudy.review.length }}</div>
|
||||
<div class="text">复习数</div>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col items-center">
|
||||
<div class="text-4xl font-bold">{{
|
||||
currentStudy.new.length + currentStudy.review.length + currentStudy.write.length
|
||||
}}</div>
|
||||
<div class="text">默写数</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="rounded-xl bg-slate-800 flex items-center gap-2 py-3 px-5 text-white cursor-pointer"
|
||||
@click="nav('study-word',{},currentStudy)">
|
||||
@click="study">
|
||||
<span>开始学习</span>
|
||||
<Icon icon="icons8:right-round" class="text-2xl"/>
|
||||
</div>
|
||||
@@ -178,7 +192,8 @@ onMounted(() => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.card {
|
||||
@apply rounded-xl bg-white p-4 mt-5;
|
||||
@apply rounded-xl p-4 mt-5;
|
||||
background: var(--color-second-bg);
|
||||
}
|
||||
|
||||
.center {
|
||||
|
||||
@@ -130,13 +130,14 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
length: 2607,
|
||||
translateLanguage: 'common',
|
||||
language: 'en',
|
||||
type: DictType.word
|
||||
type: DictType.word,
|
||||
statistics: []
|
||||
},
|
||||
],
|
||||
currentStudy: {
|
||||
word: {
|
||||
dictIndex: 0,
|
||||
perDayStudyNumber: 5,
|
||||
perDayStudyNumber: 20,
|
||||
lastLearnIndex: 0,
|
||||
},
|
||||
article: {
|
||||
@@ -265,6 +266,9 @@ export const useBaseStore = defineStore('base', {
|
||||
currentStudyWordDict(): Dict {
|
||||
return this.wordDictList[this.currentStudy.word.dictIndex] ?? getDefaultDict()
|
||||
},
|
||||
sword() {
|
||||
return this.currentStudy.word
|
||||
},
|
||||
currentStudyWordProgress(): number {
|
||||
if (!this.currentStudyWordDict.words?.length) return 0
|
||||
return Number(((this.currentStudy.word.lastLearnIndex / this.currentStudyWordDict.words?.length) * 100).toFixed())
|
||||
@@ -313,54 +317,25 @@ export const useBaseStore = defineStore('base', {
|
||||
} catch (e) {
|
||||
console.error('读取本地dict数据失败', e)
|
||||
}
|
||||
const runtimeStore = useRuntimeStore()
|
||||
|
||||
//自定义的词典,文章只删除了sections,单词并未做删除,所以这里不需要处理
|
||||
if (this.currentDict.isCustom) {
|
||||
|
||||
if (this.current.index < 3) {
|
||||
//前三本词典的isCustom为true。数据全都保存了,不需要处理了
|
||||
} else {
|
||||
//自定义的词典,文章只删除了sections,单词并未做删除,所以这里不需要处理
|
||||
if (this.currentDict.isCustom) {
|
||||
|
||||
} else {
|
||||
//处理非自定义的情况。
|
||||
let dictResourceUrl = `./dicts/${this.currentDict.language}/${this.currentDict.type}/${this.currentDict.translateLanguage}/${this.currentDict.url}`;
|
||||
if ([DictType.word].includes(this.currentDict.type)) {
|
||||
if (!this.currentDict.originWords.length) {
|
||||
let v = await getDictFile(dictResourceUrl)
|
||||
// v = v.slice(0, 50)
|
||||
v.map(s => {
|
||||
s.id = nanoid(6)
|
||||
})
|
||||
this.currentDict.originWords = cloneDeep(v)
|
||||
this.currentDict.words = cloneDeep(v)
|
||||
this.currentDict.chapterWords = chunk(this.currentDict.words, this.currentDict.chapterWordNumber)
|
||||
}
|
||||
}
|
||||
|
||||
if ([DictType.article].includes(this.currentDict.type)) {
|
||||
if (!this.currentDict.articles.length) {
|
||||
let s = await getDictFile(dictResourceUrl)
|
||||
this.currentDict.articles = cloneDeep(s.map(v => {
|
||||
v.id = nanoid(6)
|
||||
return v
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let currentDict = this.wordDictList[this.currentStudy.word.dictIndex]
|
||||
let dictResourceUrl = `./dicts/${currentDict.language}/${currentDict.type}/${currentDict.translateLanguage}/${currentDict.url}`;
|
||||
if (!currentDict.originWords.length) {
|
||||
if (!currentDict.words.length) {
|
||||
let v = await getDictFile(dictResourceUrl)
|
||||
// v = v.slice(0, 50)
|
||||
v.map(s => {
|
||||
s.id = nanoid(6)
|
||||
})
|
||||
currentDict.originWords = cloneDeep(v)
|
||||
currentDict.words = cloneDeep(v)
|
||||
currentDict.chapterWords = chunk(currentDict.words, currentDict.chapterWordNumber)
|
||||
// currentDict.originWords = cloneDeep(v)
|
||||
// currentDict.words = cloneDeep(v)
|
||||
currentDict.words = Object.freeze(v)
|
||||
}
|
||||
|
||||
currentDict = this.articleDictList[this.currentStudy.article.dictIndex]
|
||||
@@ -373,7 +348,7 @@ export const useBaseStore = defineStore('base', {
|
||||
}))
|
||||
}
|
||||
|
||||
console.log('this.wordDictList', this.articleDictList)
|
||||
console.log('this.wordDictList', this.wordDictList[0].words[0])
|
||||
emitter.emit(EventKey.changeDict)
|
||||
resolve(true)
|
||||
})
|
||||
|
||||
@@ -10,6 +10,8 @@ export interface PracticeState {
|
||||
inputWordNumber: number,//当前总输入了多少个单词(不包含跳过)
|
||||
wrongWordNumber: number,
|
||||
correctRate: number,
|
||||
startIndex:number,
|
||||
endIndex:number,
|
||||
}
|
||||
|
||||
export const usePracticeStore = defineStore('practice', {
|
||||
@@ -21,6 +23,8 @@ export const usePracticeStore = defineStore('practice', {
|
||||
correctRate: -1,
|
||||
total: 0,
|
||||
index: 0,
|
||||
startIndex: 0,
|
||||
endIndex: 0,
|
||||
newWordNumber: 0,
|
||||
inputWordNumber: 0,
|
||||
wrongWordNumber: 0,
|
||||
|
||||
Reference in New Issue
Block a user