save
This commit is contained in:
3
components.d.ts
vendored
3
components.d.ts
vendored
@@ -24,6 +24,9 @@ declare module 'vue' {
|
||||
EditArticle: typeof import('./src/components/Article/EditArticle.vue')['default']
|
||||
EditBatchArticleModal: typeof import('./src/components/Article/EditBatchArticleModal.vue')['default']
|
||||
EditSingleArticleModal: typeof import('./src/components/Article/EditSingleArticleModal.vue')['default']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElForm: typeof import('element-plus/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
|
||||
@@ -38,7 +38,7 @@ watch(store.wrong.originWords, (n) => {
|
||||
store.wrong.chapterWords = [store.wrong.words]
|
||||
})
|
||||
|
||||
useStartKeyboardEventListener()
|
||||
// useStartKeyboardEventListener()
|
||||
|
||||
async function init() {
|
||||
console.time()
|
||||
|
||||
@@ -9,7 +9,7 @@ import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useDisableEventListener} from "@/hooks/event.ts";
|
||||
import {Dict, DictType, languageCategoryOptions, Sort, Word} from "@/types.ts";
|
||||
import {DefaultDict, Dict, DictType, languageCategoryOptions, Sort, Word} from "@/types.ts";
|
||||
import {onMounted, reactive, watch} from "vue";
|
||||
import {FormInstance, FormRules} from "element-plus";
|
||||
import {dictionaryResources} from "@/assets/dictionary.ts";
|
||||
@@ -39,12 +39,11 @@ let step = $ref(1)
|
||||
let isAddDict = $ref(false)
|
||||
|
||||
let list = $computed(() => {
|
||||
return store.myDicts.filter(v => v.type === DictType.customArticle)
|
||||
.concat([
|
||||
store.simple,
|
||||
store.wrong,
|
||||
store.collect
|
||||
])
|
||||
return [
|
||||
store.collect,
|
||||
store.simple,
|
||||
store.wrong
|
||||
].concat(store.myDicts.filter(v => v.type === DictType.customArticle))
|
||||
.concat([{name: '',} as any])
|
||||
})
|
||||
|
||||
@@ -99,9 +98,11 @@ onMounted(() => {
|
||||
console.log('tagList', tagList)
|
||||
})
|
||||
|
||||
function selectDict(dict: Dict) {
|
||||
// runtimeStore.editDict = cloneDeep(dict)
|
||||
runtimeStore.editDict = dict
|
||||
function selectDict(val: {
|
||||
dict: Dict,
|
||||
index: number
|
||||
}) {
|
||||
store.current.editIndex = val.index
|
||||
isAddDict = false
|
||||
step = 1
|
||||
}
|
||||
@@ -109,31 +110,20 @@ function selectDict(dict: Dict) {
|
||||
async function onSubmit() {
|
||||
await dictFormRef.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
let data = {
|
||||
sort: Sort.normal,
|
||||
type: DictType.customArticle,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 30,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: [],
|
||||
articles: [],
|
||||
url: '',
|
||||
let data: Dict = {
|
||||
...DefaultDict,
|
||||
...dictForm,
|
||||
}
|
||||
if (dictForm.id) {
|
||||
let rIndex = store.myDicts.findIndex(v => v.id === dictForm.id)
|
||||
runtimeStore.editDict = data
|
||||
store.myDicts[rIndex] = cloneDeep(data)
|
||||
isAddDict = false
|
||||
} else {
|
||||
if (store.myDicts.find(v => v.name === dictForm.name)) {
|
||||
return ElMessage.warning('已有相同名称词典!')
|
||||
} else {
|
||||
runtimeStore.editDict = data
|
||||
store.myDicts.push(cloneDeep(data))
|
||||
store.current.editIndex = store.myDicts.length - 1
|
||||
isAddDict = false
|
||||
console.log('submit!', data)
|
||||
}
|
||||
@@ -145,8 +135,8 @@ async function onSubmit() {
|
||||
}
|
||||
|
||||
function editDict() {
|
||||
dictForm.name = runtimeStore.editDict.name
|
||||
dictForm.description = runtimeStore.editDict.description
|
||||
dictForm.name = store.editDict.name
|
||||
dictForm.description = store.editDict.description
|
||||
wordFormMode = FormMode.None;
|
||||
isAddDict = true
|
||||
}
|
||||
@@ -171,23 +161,30 @@ const wordRules = reactive<FormRules>({
|
||||
{max: 30, message: '名称不能超过30个字符', trigger: 'blur'},
|
||||
],
|
||||
})
|
||||
let wordListRef: any = $ref()
|
||||
|
||||
async function onSubmitWord() {
|
||||
await wordFormRef.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
if (wordFormMode === FormMode.Add) {
|
||||
if (runtimeStore.editDict.originWords.find(v => v.name === wordForm.name)) {
|
||||
if (store.editDict.originWords.find(v => v.name === wordForm.name)) {
|
||||
return ElMessage.warning('已有相同名称单词!')
|
||||
} else {
|
||||
// let list = cloneDeep(store.editDict.originWords)
|
||||
let data: any = cloneDeep(wordForm)
|
||||
if (data.trans) {
|
||||
data.trans = data.trans.split('\n');
|
||||
} else {
|
||||
data.trans = []
|
||||
}
|
||||
runtimeStore.editDict.originWords.push(data)
|
||||
store.editDict.originWords.push(data)
|
||||
console.log('wordListRef',wordListRef)
|
||||
wordListRef?.reset()
|
||||
// store.editDict.originWords = list
|
||||
//因为虚拟列表,必须重新赋值才能检测到更新
|
||||
// store.editDict.originWords = cloneDeep(store.editDict.originWords)
|
||||
}
|
||||
console.log('runtimeStore.editDict', runtimeStore.editDict)
|
||||
console.log('store.editDict', store.editDict)
|
||||
}
|
||||
} else {
|
||||
ElMessage.warning('请填写完整')
|
||||
@@ -245,10 +242,10 @@ const {
|
||||
<div class="detail" v-if="!isAddDict">
|
||||
<div class="dict">
|
||||
<div class="info">
|
||||
<div class="name">{{ runtimeStore.editDict.name }}</div>
|
||||
<div class="desc">{{ runtimeStore.editDict.description }}</div>
|
||||
<div class="name">{{ store.editDict.name }}</div>
|
||||
<div class="desc">{{ store.editDict.description }}</div>
|
||||
<div class="more-info">
|
||||
<div class="item">词汇量:{{ runtimeStore.editDict.originWords.length }}词</div>
|
||||
<div class="item">词汇量:{{ store.editDict.originWords.length }}词</div>
|
||||
<div class="item">创建日期:-</div>
|
||||
<div class="item">花费时间:-</div>
|
||||
<div class="item">累积错误:-</div>
|
||||
@@ -293,25 +290,19 @@ const {
|
||||
<div class="list-header">
|
||||
<div class="name">单词列表</div>
|
||||
<div class="flex-center gap10">
|
||||
<div class="name">{{ store.currentDict.originWords.length }}个单词</div>
|
||||
<div class="name">{{ store.editDict.originWords.length }}个单词</div>
|
||||
<BaseIcon icon="mi:add"
|
||||
@click='wordFormMode = FormMode.Add'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <WordList-->
|
||||
<!-- v-if="runtimeStore.editDict.originWords.length"-->
|
||||
<!-- class="word-list"-->
|
||||
<!-- :is-active="true"-->
|
||||
<!-- @change="(i:number) => data.index = i"-->
|
||||
<!-- :list="runtimeStore.editDict.originWords"-->
|
||||
<!-- :activeIndex="data.index"/>-->
|
||||
<WordList2
|
||||
v-if="store.currentDict.words.length"
|
||||
ref="wordListRef"
|
||||
v-if="store.editDict.originWords.length"
|
||||
class="word-list"
|
||||
:is-active="true"
|
||||
@change="(i:number) => data.index = i"
|
||||
:list="store.currentDict.words"
|
||||
:list="store.editDict.originWords"
|
||||
:activeIndex="data.index">
|
||||
<template v-slot="{word}">
|
||||
<BaseIcon
|
||||
|
||||
@@ -158,7 +158,7 @@ onUnmounted(() => {
|
||||
<PracticeWord ref="practiceRef" v-else/>
|
||||
<Footer/>
|
||||
</div>
|
||||
<!-- <AddWordDialog></AddWordDialog>-->
|
||||
<AddWordDialog></AddWordDialog>
|
||||
<DictModal :model-value="runtimeStore.showDictModal" @close="runtimeStore.showDictModal = false"/>
|
||||
<SettingModal v-if="runtimeStore.showSettingModal" @close="runtimeStore.showSettingModal = false"/>
|
||||
<Statistics/>
|
||||
|
||||
@@ -8,7 +8,7 @@ const props = defineProps<{
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
selectDict: [val: Dict]
|
||||
selectDict: [val: { dict: Dict, index: number }]
|
||||
detail: [],
|
||||
add: []
|
||||
}>()
|
||||
@@ -17,17 +17,17 @@ const emit = defineEmits<{
|
||||
|
||||
<template>
|
||||
<div class="dict-list">
|
||||
<template v-for="i in list">
|
||||
<template v-for="(dict,index) in list">
|
||||
<div class="dict-item anim"
|
||||
:class="selectDictName === i.name && 'active'"
|
||||
@click="emit('selectDict',i)"
|
||||
v-if="i.name"
|
||||
:class="selectDictName === dict.name && 'active'"
|
||||
@click="emit('selectDict',{dict,index})"
|
||||
v-if="dict.name"
|
||||
>
|
||||
<div class="name">{{ i.name }}</div>
|
||||
<div class="desc">{{ i.description }}</div>
|
||||
<div class="num">{{ i.length }}词</div>
|
||||
<div class="name">{{ dict.name }}</div>
|
||||
<div class="desc">{{ dict.description }}</div>
|
||||
<div class="num">{{ dict.length }}词</div>
|
||||
|
||||
<Icon icon="octicon:arrow-right-24" v-if="selectDictName === i.name"
|
||||
<Icon icon="octicon:arrow-right-24" v-if="selectDictName === dict.name"
|
||||
@click.stop="emit('detail')"
|
||||
class="go" width="20" color="#929596"/>
|
||||
</div>
|
||||
|
||||
@@ -6,27 +6,15 @@ import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
list?: Word[],
|
||||
activeIndex?: number,
|
||||
showDel?: boolean,
|
||||
isActive?: boolean
|
||||
active?: boolean
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
word: Word
|
||||
}>(), {
|
||||
activeIndex: -1,
|
||||
isActive: false,
|
||||
showDel: false,
|
||||
showTranslate: true,
|
||||
showWord: true
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
del: [val: Word],
|
||||
change: [i: number]
|
||||
}>()
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
const {
|
||||
isWordCollect,
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
import {Word} from "../../types.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import WordItem from "@/components/list/WordItem.vue";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {watch} from 'vue'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
list: Word[],
|
||||
@@ -24,30 +27,38 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
//
|
||||
// const listRef: HTMLElement = $ref(null as any)
|
||||
//
|
||||
// function scrollViewToCenter(index: number) {
|
||||
// if (index === -1) return
|
||||
// listRef.children[index]?.scrollIntoView({block: 'center', behavior: 'smooth'})
|
||||
// }
|
||||
//
|
||||
// watch(() => props.activeIndex, (n: any) => {
|
||||
// if (settingStore.showPanel) {
|
||||
// scrollViewToCenter(n)
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// watch(() => props.isActive, (n: boolean) => {
|
||||
// setTimeout(() => {
|
||||
// if (n) scrollViewToCenter(props.activeIndex)
|
||||
// }, 300)
|
||||
// })
|
||||
//
|
||||
const listRef: any = $ref()
|
||||
|
||||
function scrollViewToCenter(index: number) {
|
||||
if (index === -1) return
|
||||
listRef.scrollToIndex(index)
|
||||
// listRef.children[index]?.scrollIntoView({block: 'center', behavior: 'smooth'})
|
||||
}
|
||||
|
||||
watch(() => props.activeIndex, (n: any) => {
|
||||
if (settingStore.showPanel) {
|
||||
scrollViewToCenter(n)
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => props.isActive, (n: boolean) => {
|
||||
setTimeout(() => {
|
||||
if (n) scrollViewToCenter(props.activeIndex)
|
||||
}, 300)
|
||||
})
|
||||
|
||||
// watch(() => props.list, () => {
|
||||
// listRef.scrollTo(0, 0)
|
||||
// })
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
|
||||
function reset() {
|
||||
listRef.reset()
|
||||
}
|
||||
|
||||
defineExpose({reset})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -56,12 +67,28 @@ const settingStore = useSettingStore()
|
||||
data-key="name"
|
||||
:data-sources="list"
|
||||
:estimate-size="85"
|
||||
ref="listRef"
|
||||
item-class="dict-virtual-item"
|
||||
>
|
||||
<template #={source}>
|
||||
<WordItem :word="source">
|
||||
<slot :word="source"></slot>
|
||||
</WordItem>
|
||||
<template #={source,index}>
|
||||
<div class="common-list-item"
|
||||
:class="{active:activeIndex === index}"
|
||||
@click="emit('change',index)"
|
||||
>
|
||||
<div class="left">
|
||||
<div class="item-title">
|
||||
<span class="word" :class="!showWord && 'text-shadow'">{{ source.name }}</span>
|
||||
<span class="phonetic">{{ source.usphone }}</span>
|
||||
<VolumeIcon class="volume" @click="playWordAudio(source.name)"></VolumeIcon>
|
||||
</div>
|
||||
<div class="item-sub-title" v-if="source.trans.length && showTranslate">
|
||||
<div v-for="item in source.trans">{{ item }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<slot :word="source"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</virtual-list>
|
||||
</template>
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface State {
|
||||
current: {
|
||||
dictType: DictType,
|
||||
index: number,
|
||||
editIndex: number,
|
||||
practiceType: DictType,//练习类型,目前仅词典为collect时判断是练单词还是文章使用
|
||||
},
|
||||
simpleWords: string[],
|
||||
@@ -109,6 +110,7 @@ export const useBaseStore = defineStore('base', {
|
||||
current: {
|
||||
dictType: DictType.word,
|
||||
index: 1,
|
||||
editIndex: 0,
|
||||
// dictType: DictType.article,
|
||||
// index: 0,
|
||||
practiceType: DictType.word,
|
||||
@@ -141,6 +143,21 @@ export const useBaseStore = defineStore('base', {
|
||||
DictType.customArticle
|
||||
].includes(state.current.dictType)
|
||||
},
|
||||
editDict(state: State) {
|
||||
if (state.current.editIndex === -1) {
|
||||
return cloneDeep(DefaultDict)
|
||||
}
|
||||
switch (state.current.editIndex) {
|
||||
case 0:
|
||||
return state.collect
|
||||
case 1:
|
||||
return state.simple
|
||||
case 2:
|
||||
return state.wrong
|
||||
default:
|
||||
return state.myDicts[state.current.editIndex]
|
||||
}
|
||||
},
|
||||
currentDict(state: State): Dict {
|
||||
switch (state.current.dictType) {
|
||||
case DictType.collect:
|
||||
|
||||
Reference in New Issue
Block a user