This commit is contained in:
Zyronon
2025-12-16 02:07:19 +08:00
parent 4c62f7a77f
commit a4a8f88362
5 changed files with 498 additions and 443 deletions

View File

@@ -199,7 +199,8 @@ html.dark {
font-family: var(--font-family);
}
html, body {
html,
body {
//font-size: 1px;
padding: 0;
margin: 0;
@@ -244,7 +245,7 @@ html, body {
display: flex;
flex-direction: column;
& > .page-content {
&>.page-content {
padding: 10rem;
box-sizing: border-box;
overflow: auto;
@@ -275,10 +276,12 @@ a {
width: .5rem;
height: .6rem;
}
::-webkit-scrollbar-track {
background: transparent;
border-radius: .1rem;
}
::-webkit-scrollbar-thumb {
background: var(--color-scrollbar);
border-radius: .6rem;
@@ -439,6 +442,7 @@ a {
.center {
@apply flex justify-center items-center;
}
.center-col {
@extend .center;
@apply flex-col;
@@ -499,9 +503,12 @@ a {
}
@keyframes underline {
0%, 100% {
0%,
100% {
border-left: .1rem solid var(--color-article);
}
50% {
border-left: .1rem solid transparent;
}
@@ -521,4 +528,10 @@ a {
background: transparent;
font-size: 16px; // 防止iOS缩放
color: transparent; // 文字透明
}
.btn-no-margin {
.base-button + .base-button {
margin-left: 0!important;
}
}

View File

@@ -48,6 +48,7 @@ const emit = defineEmits<{
}],
importData: [e: Event]
exportData: []
sort: [type: Sort,pageNo: number,pageSize: number]
}>()
let listRef: any = $ref()
@@ -85,11 +86,6 @@ let selectAll = $computed(() => {
return !!selectIds.length
})
let list2 = $ref([])
onMounted(async () => {
list2 = await props.request({ pageNo, pageSize })
console.log('list2',list2)
})
function toggleSelect(item) {
let rIndex = selectIds.findIndex(v => v === item.id)
@@ -117,12 +113,16 @@ const closeImportDialog = () => showImportDialog = false
function sort(type: Sort) {
if (type === Sort.reverse) {
Toast.success('已翻转排序')
list.value = reverse(cloneDeep(list.value))
emit('sort', type,pageNo,pageSize)
}
if (type === Sort.random) {
Toast.success('已随机排序')
list.value = shuffle(cloneDeep(list.value))
emit('sort', type,pageNo,pageSize)
}
if (type === Sort.reverseAll) {
emit('sort', type,1,total2)
}
if (type === Sort.randomAll) {
emit('sort', type,1,total2)
}
showSortDialog = false
}
@@ -134,6 +134,7 @@ function handleBatchDel() {
function handlePageNo(e) {
pageNo = e
getData()
scrollToTop()
}
@@ -142,9 +143,29 @@ const s = useSlots()
defineExpose({
scrollToBottom,
scrollToItem,
closeImportDialog
closeImportDialog,
getData
})
let list2 = $ref([])
let loading2 = $ref(false)
let total2 = $ref(0)
async function getData() {
loading2 = true
let {list, total} = await props.request({ pageNo, pageSize })
console.log('list2',list2)
list2 = list
total2 = total
loading2 = false
}
onMounted(async () => {
getData()
})
defineRender(
() => {
const d = (item) => <Checkbox
@@ -234,10 +255,12 @@ defineRender(
<div class="mini-row-title">
列表顺序设置
</div>
<div class="mini-row">
<BaseButton size="small" onClick={() => sort(Sort.reverse)}>翻转
</BaseButton>
<BaseButton size="small" onClick={() => sort(Sort.random)}>随机</BaseButton>
<div class="flex flex-col gap2 btn-no-margin">
<BaseButton onClick={() => sort(Sort.reverse)}>翻转当前页</BaseButton>
<BaseButton onClick={() => sort(Sort.reverseAll)}>翻转所有</BaseButton>
<div class="line"></div>
<BaseButton onClick={() => sort(Sort.reverse)}>随机当前页</BaseButton>
<BaseButton onClick={() => sort(Sort.randomAll)}>随机所有</BaseButton>
</div>
</MiniDialog>
</div>
@@ -247,15 +270,15 @@ defineRender(
</div>
}
{
props.loading ?
loading2 ?
<div class="h-full w-full center text-4xl">
<IconEosIconsLoading color="gray"/>
</div>
: currentList.length ? (
: list2.length ? (
<>
<div class="flex-1 overflow-auto"
ref={e => listRef = e}>
{currentList.map((item, index) => {
{list2.map((item, index) => {
return (
<div class="list-item-wrapper"
key={item.word}
@@ -274,7 +297,7 @@ defineRender(
onUpdate:page-size={(e) => pageSize = e}
pageSizes={[20, 50, 100, 200]}
layout="prev, pager, next"
total={props.total}/>
total={total2}/>
</div>
}
</>
@@ -316,6 +339,4 @@ defineRender(
}
)
</script>
<style scoped lang="scss">
</style>
<style scoped lang="scss"></style>

View File

@@ -1,10 +1,10 @@
<script setup lang="tsx">
import { DictId } from "@/types/types.ts";
import { DictId, Sort } from "@/types/types.ts";
import BasePage from "@/components/BasePage.vue";
import { computed, onMounted, reactive, ref, shallowReactive, watch } from "vue";
import { useRuntimeStore } from "@/stores/runtime.ts";
import { _getDictDataByUrl, _nextTick, convertToWord, isMobile, loadJsLib, useNav } from "@/utils";
import { _getDictDataByUrl, _nextTick, cloneDeep, convertToWord, isMobile, loadJsLib, reverse, shuffle, useNav } from "@/utils";
import { nanoid } from "nanoid";
import BaseIcon from "@/components/BaseIcon.vue";
import BaseTable from "@/components/BaseTable.vue";
@@ -152,7 +152,7 @@ function word2Str(word) {
res.phrases = word.phrases.map(v => (v.c + "\n" + v.cn).replaceAll('"', '')).join('\n\n')
res.synos = word.synos.map(v => (v.pos + v.cn + "\n" + v.ws.join('/')).replaceAll('"', '')).join('\n\n')
res.relWords = word.relWords.root ? ('词根:' + word.relWords.root + '\n\n' +
word.relWords.rels.map(v => (v.pos + "\n" + v.words.map(v => (v.c + ':' + v.cn)).join('\n')).replaceAll('"', '')).join('\n\n')) : ''
word.relWords.rels.map(v => (v.pos + "\n" + v.words.map(v => (v.c + ':' + v.cn)).join('\n')).replaceAll('"', '')).join('\n\n')) : ''
res.etymology = word.etymology.map(v => (v.t + '\n' + v.d).replaceAll('"', '')).join('\n\n')
return res
}
@@ -193,8 +193,8 @@ onMounted(async () => {
router.push("/word")
} else {
if (!runtimeStore.editDict.words.length
&& !runtimeStore.editDict.custom
&& ![DictId.wordCollect, DictId.wordWrong, DictId.wordKnown].includes(runtimeStore.editDict.en_name || runtimeStore.editDict.id)
&& !runtimeStore.editDict.custom
&& ![DictId.wordCollect, DictId.wordWrong, DictId.wordKnown].includes(runtimeStore.editDict.en_name || runtimeStore.editDict.id)
) {
loading = true
let r = await _getDictDataByUrl(runtimeStore.editDict)
@@ -213,6 +213,7 @@ onMounted(async () => {
}
list2 = runtimeStore.editDict.words
loading = false
tableRef.value.getData()
}
}
})
@@ -319,22 +320,22 @@ function importData(e) {
if (repeat.length) {
MessageBox.confirm(
'单词"' + repeat.map(v => v.word).join(', ') + '" 已存在,是否覆盖原单词?',
'检测到重复单词',
() => {
repeat.map(v => {
runtimeStore.editDict.words[v.index] = v
delete runtimeStore.editDict.words[v.index]["index"]
})
},
null,
() => {
tableRef.value.closeImportDialog()
e.target.value = ''
importLoading = false
syncDictInMyStudyList()
Toast.success('导入成功!')
}
'单词"' + repeat.map(v => v.word).join(', ') + '" 已存在,是否覆盖原单词?',
'检测到重复单词',
() => {
repeat.map(v => {
runtimeStore.editDict.words[v.index] = v
delete runtimeStore.editDict.words[v.index]["index"]
})
},
null,
() => {
tableRef.value.closeImportDialog()
e.target.value = ''
importLoading = false
syncDictInMyStudyList()
Toast.success('导入成功!')
}
)
} else {
tableRef.value.closeImportDialog()
@@ -447,216 +448,238 @@ async function requestList({ pageNo, pageSize }) {
if (AppEnv.CAN_REQUEST) {
} else {
return list2.slice((pageNo - 1) * pageSize, (pageNo - 1) * pageSize + pageSize)
return {
list: list2.slice((pageNo - 1) * pageSize, (pageNo - 1) * pageSize + pageSize),
total: list2.length
}
}
}
function sort(type: Sort, pageNo: number, pageSize: number) {
debugger
console.log('sort', type)
if ([Sort.reverse, Sort.random].includes(type)) {
list2 = list2.slice(0, pageSize * (pageNo - 1))
.concat(reverse(list2.slice(pageSize * (pageNo - 1), pageSize * (pageNo - 1) + pageSize)))
.concat(list2.slice(pageSize * (pageNo - 1) + pageSize))
} else if ([Sort.reverseAll, Sort.randomAll].includes(type)) {
list2 = list2.slice(0, pageSize * (pageNo - 1))
.concat(shuffle(list2.slice(pageSize * (pageNo - 1), pageSize * (pageNo - 1) + pageSize)))
.concat(list2.slice(pageSize * (pageNo - 1) + pageSize))
}
runtimeStore.editDict.words = list2
Toast.success('已排序成功')
tableRef.value.getData()
}
defineRender(() => {
return (
<BasePage>
{
showBookDetail.value ? <div className="card mb-0 dict-detail-card flex flex-col">
<div class="dict-header flex justify-between items-center relative">
<BackIcon class="dict-back z-2"/>
<div class="dict-title absolute page-title text-align-center w-full">{runtimeStore.editDict.name}</div>
<div class="dict-actions flex">
<BaseButton loading={studyLoading || loading} type="info"
onClick={() => isEdit = true}>编辑</BaseButton>
<BaseButton id="study" loading={studyLoading || loading} onClick={addMyStudyList}>学习</BaseButton>
<BaseButton loading={studyLoading || loading} onClick={startTest}>测试</BaseButton>
</div>
</div>
<div class="text-lg mt-2">介绍{runtimeStore.editDict.description}</div>
<div class="line my-3"></div>
<BasePage>
{
showBookDetail.value ? <div className="card mb-0 dict-detail-card flex flex-col">
<div class="dict-header flex justify-between items-center relative">
<BackIcon class="dict-back z-2" />
<div class="dict-title absolute page-title text-align-center w-full">{runtimeStore.editDict.name}</div>
<div class="dict-actions flex">
<BaseButton loading={studyLoading || loading} type="info"
onClick={() => isEdit = true}>编辑</BaseButton>
<BaseButton id="study" loading={studyLoading || loading} onClick={addMyStudyList}>学习</BaseButton>
<BaseButton loading={studyLoading || loading} onClick={startTest}>测试</BaseButton>
</div>
</div>
<div class="text-lg mt-2">介绍{runtimeStore.editDict.description}</div>
<div class="line my-3"></div>
{/* 移动端标签页导航 */}
{isMob && isOperate && (
<div class="tab-navigation mb-3">
<div
class={`tab-item ${activeTab === 'list' ? 'active' : ''}`}
onClick={() => activeTab = 'list'}
>
单词列表
</div>
<div
class={`tab-item ${activeTab === 'edit' ? 'active' : ''}`}
onClick={() => activeTab = 'edit'}
>
{wordForm.id ? '编辑' : '添加'}单词
</div>
</div>
)}
<div class="flex flex-1 overflow-hidden content-area">
<div class={`word-list-section ${isMob && isOperate && activeTab !== 'list' ? 'mobile-hidden' : ''}`}>
<BaseTable
ref={tableRef}
class="h-full"
request={requestList}
list={list}
total={runtimeStore.editDict.length}
loading={loading}
onUpdate:list={e => list = e}
del={delWord}
batchDel={batchDel}
add={addWord}
onImportData={importData}
onExportData={exportData}
exportLoading={exportLoading}
importLoading={importLoading}
>
{
(val) =>
<WordItem
showTransPop={false}
item={val.item}>
{{
prefix: () => val.checkbox(val.item),
suffix: () => (
<div class='flex flex-col'>
<BaseIcon
class="option-icon"
onClick={() => editWord(val.item)}
title="编辑">
<IconFluentTextEditStyle20Regular/>
</BaseIcon>
<PopConfirm title="确认删除?"
onConfirm={() => delWord(val.item.id)}
>
<BaseIcon
class="option-icon"
title="删除">
<DeleteIcon/>
</BaseIcon>
</PopConfirm>
</div>
)
}}
</WordItem>
}
</BaseTable>
</div>
{
isOperate ? (
<div
class={`edit-section flex-1 flex flex-col ${isMob && activeTab !== 'edit' ? 'mobile-hidden' : ''}`}>
<div class="common-title">
{wordForm.id ? '修改' : '添加'}单词
</div>
<Form
class="flex-1 overflow-auto pr-2"
ref={e => wordFormRef = e}
rules={wordRules}
model={wordForm}
label-width="7rem">
<FormItem label="单词" prop="word">
<BaseInput
modelValue={wordForm.word}
onUpdate:modelValue={e => wordForm.word = e}
>
</BaseInput>
</FormItem>
<FormItem label="英音音标">
<BaseInput
modelValue={wordForm.phonetic0}
onUpdate:modelValue={e => wordForm.phonetic0 = e}
/>
</FormItem>
<FormItem label="美音音标">
<BaseInput
modelValue={wordForm.phonetic1}
onUpdate:modelValue={e => wordForm.phonetic1 = e}/>
</FormItem>
<FormItem label="翻译">
<Textarea
modelValue={wordForm.trans}
onUpdate:modelValue={e => wordForm.trans = e}
placeholder="一行一个翻译前面词性后面内容如n.取消);多个翻译请换行"
autosize={{ minRows: 6, maxRows: 10 }}/>
</FormItem>
<FormItem label="例句">
<Textarea
modelValue={wordForm.sentences}
onUpdate:modelValue={e => wordForm.sentences = e}
placeholder="一行原文,一行译文;多个请换两行"
autosize={{ minRows: 6, maxRows: 10 }}/>
</FormItem>
<FormItem label="短语">
<Textarea
modelValue={wordForm.phrases}
onUpdate:modelValue={e => wordForm.phrases = e}
placeholder="一行原文,一行译文;多个请换两行"
autosize={{ minRows: 6, maxRows: 10 }}/>
</FormItem>
<FormItem label="同义词">
<Textarea
modelValue={wordForm.synos}
onUpdate:modelValue={e => wordForm.synos = e}
placeholder="请参考已有单词格式"
autosize={{ minRows: 6, maxRows: 20 }}/>
</FormItem>
<FormItem label="同根词">
<Textarea
modelValue={wordForm.relWords}
onUpdate:modelValue={e => wordForm.relWords = e}
placeholder="请参考已有单词格式"
autosize={{ minRows: 6, maxRows: 20 }}/>
</FormItem>
<FormItem label="词源">
<Textarea
modelValue={wordForm.etymology}
onUpdate:modelValue={e => wordForm.etymology = e}
placeholder="请参考已有单词格式"
autosize={{ minRows: 6, maxRows: 10 }}/>
</FormItem>
</Form>
<div class="center">
<BaseButton
type="info"
onClick={closeWordForm}>关闭
</BaseButton>
<BaseButton type="primary"
onClick={onSubmitWord}>保存
</BaseButton>
</div>
</div>
) : null
}
</div>
</div> :
<div class="card mb-0 dict-detail-card">
<div class="dict-header flex justify-between items-center relative">
<BackIcon class="dict-back z-2" onClick={() => {
if (isAdd) {
router.back()
} else {
isEdit = false
}
}}/>
<div class="dict-title absolute page-title text-align-center w-full">
{runtimeStore.editDict.id ? '修改' : '创建'}词典
</div>
</div>
<div class="center">
<EditBook
isAdd={isAdd}
isBook={false}
onClose={formClose}
onSubmit={() => isEdit = isAdd = false}
/>
</div>
{/* 移动端标签页导航 */}
{isMob && isOperate && (
<div class="tab-navigation mb-3">
<div
class={`tab-item ${activeTab === 'list' ? 'active' : ''}`}
onClick={() => activeTab = 'list'}
>
单词列表
</div>
}
<div
class={`tab-item ${activeTab === 'edit' ? 'active' : ''}`}
onClick={() => activeTab = 'edit'}
>
{wordForm.id ? '编辑' : '添加'}单词
</div>
</div>
)}
<PracticeSettingDialog
showLeftOption
modelValue={showPracticeSettingDialog}
onUpdate:modelValue={val => (showPracticeSettingDialog = val)}
onOk={startPractice}/>
</BasePage>
<div class="flex flex-1 overflow-hidden content-area">
<div class={`word-list-section ${isMob && isOperate && activeTab !== 'list' ? 'mobile-hidden' : ''}`}>
<BaseTable
sort={sort}
ref={tableRef}
class="h-full"
request={requestList}
list={list}
total={runtimeStore.editDict.length}
loading={loading}
onUpdate:list={e => list = e}
del={delWord}
batchDel={batchDel}
add={addWord}
onImportData={importData}
onExportData={exportData}
exportLoading={exportLoading}
importLoading={importLoading}
>
{
(val) =>
<WordItem
showTransPop={false}
item={val.item}>
{{
prefix: () => val.checkbox(val.item),
suffix: () => (
<div class='flex flex-col'>
<BaseIcon
class="option-icon"
onClick={() => editWord(val.item)}
title="编辑">
<IconFluentTextEditStyle20Regular />
</BaseIcon>
<PopConfirm title="确认删除?"
onConfirm={() => delWord(val.item.id)}
>
<BaseIcon
class="option-icon"
title="删除">
<DeleteIcon />
</BaseIcon>
</PopConfirm>
</div>
)
}}
</WordItem>
}
</BaseTable>
</div>
{
isOperate ? (
<div
class={`edit-section flex-1 flex flex-col ${isMob && activeTab !== 'edit' ? 'mobile-hidden' : ''}`}>
<div class="common-title">
{wordForm.id ? '修改' : '添加'}单词
</div>
<Form
class="flex-1 overflow-auto pr-2"
ref={e => wordFormRef = e}
rules={wordRules}
model={wordForm}
label-width="7rem">
<FormItem label="单词" prop="word">
<BaseInput
modelValue={wordForm.word}
onUpdate:modelValue={e => wordForm.word = e}
>
</BaseInput>
</FormItem>
<FormItem label="英音音标">
<BaseInput
modelValue={wordForm.phonetic0}
onUpdate:modelValue={e => wordForm.phonetic0 = e}
/>
</FormItem>
<FormItem label="美音音标">
<BaseInput
modelValue={wordForm.phonetic1}
onUpdate:modelValue={e => wordForm.phonetic1 = e} />
</FormItem>
<FormItem label="翻译">
<Textarea
modelValue={wordForm.trans}
onUpdate:modelValue={e => wordForm.trans = e}
placeholder="一行一个翻译前面词性后面内容如n.取消);多个翻译请换行"
autosize={{ minRows: 6, maxRows: 10 }} />
</FormItem>
<FormItem label="例句">
<Textarea
modelValue={wordForm.sentences}
onUpdate:modelValue={e => wordForm.sentences = e}
placeholder="一行原文,一行译文;多个请换两行"
autosize={{ minRows: 6, maxRows: 10 }} />
</FormItem>
<FormItem label="短语">
<Textarea
modelValue={wordForm.phrases}
onUpdate:modelValue={e => wordForm.phrases = e}
placeholder="一行原文,一行译文;多个请换两行"
autosize={{ minRows: 6, maxRows: 10 }} />
</FormItem>
<FormItem label="同义词">
<Textarea
modelValue={wordForm.synos}
onUpdate:modelValue={e => wordForm.synos = e}
placeholder="请参考已有单词格式"
autosize={{ minRows: 6, maxRows: 20 }} />
</FormItem>
<FormItem label="同根词">
<Textarea
modelValue={wordForm.relWords}
onUpdate:modelValue={e => wordForm.relWords = e}
placeholder="请参考已有单词格式"
autosize={{ minRows: 6, maxRows: 20 }} />
</FormItem>
<FormItem label="词源">
<Textarea
modelValue={wordForm.etymology}
onUpdate:modelValue={e => wordForm.etymology = e}
placeholder="请参考已有单词格式"
autosize={{ minRows: 6, maxRows: 10 }} />
</FormItem>
</Form>
<div class="center">
<BaseButton
type="info"
onClick={closeWordForm}>关闭
</BaseButton>
<BaseButton type="primary"
onClick={onSubmitWord}>保存
</BaseButton>
</div>
</div>
) : null
}
</div>
</div> :
<div class="card mb-0 dict-detail-card">
<div class="dict-header flex justify-between items-center relative">
<BackIcon class="dict-back z-2" onClick={() => {
if (isAdd) {
router.back()
} else {
isEdit = false
}
}} />
<div class="dict-title absolute page-title text-align-center w-full">
{runtimeStore.editDict.id ? '修改' : '创建'}词典
</div>
</div>
<div class="center">
<EditBook
isAdd={isAdd}
isBook={false}
onClose={formClose}
onSubmit={() => isEdit = isAdd = false}
/>
</div>
</div>
}
<PracticeSettingDialog
showLeftOption
modelValue={showPracticeSettingDialog}
onUpdate:modelValue={val => (showPracticeSettingDialog = val)}
onOk={startPractice} />
</BasePage>
)
})
</script>

View File

@@ -9,210 +9,206 @@ import { add2MyDict, dictListVersion, myDictList } from "@/apis";
import Toast from "@/components/base/toast/Toast.ts";
export interface BaseState {
simpleWords: string[],
load: boolean
word: {
studyIndex: number,
bookList: Dict[],
},
article: {
bookList: Dict[],
studyIndex: number,
},
dictListVersion: number
simpleWords: string[],
load: boolean
word: {
studyIndex: number,
bookList: Dict[],
},
article: {
bookList: Dict[],
studyIndex: number,
},
dictListVersion: number
}
export const getDefaultBaseState = (): BaseState => ({
simpleWords: [
'a', 'an',
'i', 'my', 'me', 'you', 'your', 'he', 'his', 'she', 'her', 'it',
'what', 'who', 'where', 'how', 'when', 'which',
'be', 'am', 'is', 'was', 'are', 'were', 'do', 'did', 'can', 'could', 'will', 'would',
'the', 'that', 'this', 'and', 'not', 'no', 'yes',
'to', 'of', 'for', 'at', 'in'
simpleWords: [
'a', 'an',
'i', 'my', 'me', 'you', 'your', 'he', 'his', 'she', 'her', 'it',
'what', 'who', 'where', 'how', 'when', 'which',
'be', 'am', 'is', 'was', 'are', 'were', 'do', 'did', 'can', 'could', 'will', 'would',
'the', 'that', 'this', 'and', 'not', 'no', 'yes',
'to', 'of', 'for', 'at', 'in'
],
load: false,
word: {
bookList: [
getDefaultDict({ id: DictId.wordCollect, en_name: DictId.wordCollect, name: '收藏' }),
getDefaultDict({ id: DictId.wordWrong, en_name: DictId.wordCollect, name: '错词' }),
getDefaultDict({
id: DictId.wordKnown,
en_name: DictId.wordCollect,
name: '已掌握',
description: '已掌握后的单词不会出现在练习中'
}),
],
load: false,
word: {
bookList: [
getDefaultDict({id: DictId.wordCollect, en_name: DictId.wordCollect, name: '收藏'}),
getDefaultDict({id: DictId.wordWrong, en_name: DictId.wordCollect, name: '错词'}),
getDefaultDict({
id: DictId.wordKnown,
en_name: DictId.wordCollect,
name: '已掌握',
description: '已掌握后的单词不会出现在练习中'
}),
],
studyIndex: -1,
},
article: {
bookList: [
getDefaultDict({id: DictId.articleCollect, en_name: DictId.articleCollect, name: '收藏'})
],
studyIndex: -1,
},
dictListVersion: 1
studyIndex: -1,
},
article: {
bookList: [
getDefaultDict({ id: DictId.articleCollect, en_name: DictId.articleCollect, name: '收藏' })
],
studyIndex: -1,
},
dictListVersion: 1
})
export const useBaseStore = defineStore('base', {
state: (): BaseState => {
return getDefaultBaseState()
state: (): BaseState => {
return getDefaultBaseState()
},
getters: {
collectWord(): Dict {
return this.word.bookList[0]
},
getters: {
collectWord(): Dict {
return this.word.bookList[0]
},
collectArticle(): Dict {
return this.article.bookList[0]
},
wrong(): Dict {
return this.word.bookList[1]
},
known(): Dict {
return this.word.bookList[2]
},
knownWords(): string[] {
return this.known.words.map((v: Word) => v.word.toLowerCase())
},
allIgnoreWords() {
return this.known.words.map((v: Word) => v.word.toLowerCase()).concat(this.simpleWords.map((v: string) => v.toLowerCase()))
},
sdict(): Dict {
if (this.word.studyIndex >= 0) {
return this.word.bookList[this.word.studyIndex] ?? getDefaultDict()
}
return getDefaultDict()
},
currentStudyProgress(): number {
if (!this.sdict.length) return 0
return _getStudyProgress(this.sdict.lastLearnIndex, this.sdict.length)
},
getDictCompleteDate(): number {
if (!this.sdict.length) return 0
if (!this.sdict.perDayStudyNumber) return 0
return Math.ceil((this.sdict.length - this.sdict.lastLearnIndex) / this.sdict.perDayStudyNumber)
},
sbook(): Dict {
return this.article.bookList[this.article.studyIndex] ?? {}
},
currentBookProgress(): number {
if (!this.sbook.length) return 0
if (this.sbook.complete) return 100
return _getStudyProgress(this.sbook.lastLearnIndex, this.sbook.length)
},
collectArticle(): Dict {
return this.article.bookList[0]
},
actions: {
setState(obj: BaseState) {
obj.word.bookList.map(book => {
book.words = shallowReactive(book.words)
book.articles = shallowReactive(book.articles)
book.statistics = shallowReactive(book.statistics)
})
obj.article.bookList.map(book => {
book.words = shallowReactive(book.words)
book.articles = shallowReactive(book.articles)
book.statistics = shallowReactive(book.statistics)
})
this.$patch(obj)
},
async init() {
return new Promise(async resolve => {
try {
let configStr: string = await get(SAVE_DICT_KEY.key)
let data = checkAndUpgradeSaveDict(configStr)
if (AppEnv.IS_OFFICIAL) {
let r = await dictListVersion()
if (r.success) {
data.dictListVersion = r.data
}
}
if (AppEnv.CAN_REQUEST) {
let res = await myDictList()
if (res.success) {
//只保留未同步的
data.word.bookList = data.word.bookList.filter(v => !v.sync)
data.article.bookList = data.article.bookList.filter(v => !v.sync)
//这里看看是否要 shallowReactive
Object.assign(data, res.data)
}
}
console.log('data', data)
this.setState(data)
set(SAVE_DICT_KEY.key, JSON.stringify({
val: shakeCommonDict(this.$state),
version: SAVE_DICT_KEY.version
}))
} catch (e) {
console.error('读取本地dict数据失败', e)
}
resolve(true)
})
},
//改变词典
async changeDict(val: Dict) {
if (AppEnv.CAN_REQUEST) {
let r = await add2MyDict({
id: val.id,
perDayStudyNumber: val.perDayStudyNumber,
lastLearnIndex: val.lastLearnIndex,
complete: val.complete,
})
if (!r.success) return Toast.error(r.msg)
else val.userDictId = r.data
}
//把其他的词典的单词数据都删掉,全保存在内存里太卡了
this.word.bookList.slice(3).map(v => {
if (!v.custom) {
v.words = shallowReactive([])
}
})
let rIndex = this.word.bookList.findIndex((v: Dict) => v.id === val.id)
if (val.words.length < val.perDayStudyNumber) {
val.perDayStudyNumber = val.words.length
}
if (rIndex > -1) {
this.word.studyIndex = rIndex
this.word.bookList[this.word.studyIndex].words = shallowReactive(val.words)
this.word.bookList[this.word.studyIndex].perDayStudyNumber = val.perDayStudyNumber
this.word.bookList[this.word.studyIndex].lastLearnIndex = val.lastLearnIndex
this.word.bookList[this.word.studyIndex].userDictId = val.userDictId
} else {
this.word.bookList.push(getDefaultDict(val))
this.word.studyIndex = this.word.bookList.length - 1
}
},
//改变书籍
async changeBook(val: Dict) {
if (AppEnv.CAN_REQUEST) {
let r = await add2MyDict({
id: val.id,
perDayStudyNumber: val.perDayStudyNumber,
lastLearnIndex: val.lastLearnIndex,
complete: val.complete,
})
if (!r.success) {
return Toast.error(r.msg)
}
}
//把其他的书籍里面的文章数据都删掉,全保存在内存里太卡了
this.article.bookList.slice(1).map(v => {
if (!v.custom) {
v.articles = shallowReactive([])
}
})
let rIndex = this.article.bookList.findIndex((v: Dict) => v.id === val.id)
if (rIndex > -1) {
this.article.studyIndex = rIndex
//不要整个等于,不然统计没了
// this.article.bookList[this.article.studyIndex] = getDefaultDict(val)
this.article.bookList[this.article.studyIndex].articles = shallowReactive(val.articles)
this.article.bookList[this.article.studyIndex].cover = val.cover
this.article.bookList[this.article.studyIndex].name = val.name
this.article.bookList[this.article.studyIndex].description = val.description
} else {
this.article.bookList.push(getDefaultDict(val))
this.article.studyIndex = this.article.bookList.length - 1
}
},
wrong(): Dict {
return this.word.bookList[1]
},
known(): Dict {
return this.word.bookList[2]
},
knownWords(): string[] {
return this.known.words.map((v: Word) => v.word.toLowerCase())
},
allIgnoreWords() {
return this.known.words.map((v: Word) => v.word.toLowerCase()).concat(this.simpleWords.map((v: string) => v.toLowerCase()))
},
sdict(): Dict {
if (this.word.studyIndex >= 0) {
return this.word.bookList[this.word.studyIndex] ?? getDefaultDict()
}
return getDefaultDict()
},
currentStudyProgress(): number {
if (!this.sdict.length) return 0
return _getStudyProgress(this.sdict.lastLearnIndex, this.sdict.length)
},
getDictCompleteDate(): number {
if (!this.sdict.length) return 0
if (!this.sdict.perDayStudyNumber) return 0
return Math.ceil((this.sdict.length - this.sdict.lastLearnIndex) / this.sdict.perDayStudyNumber)
},
sbook(): Dict {
return this.article.bookList[this.article.studyIndex] ?? {}
},
currentBookProgress(): number {
if (!this.sbook.length) return 0
if (this.sbook.complete) return 100
return _getStudyProgress(this.sbook.lastLearnIndex, this.sbook.length)
},
},
actions: {
setState(obj: BaseState) {
obj.word.bookList.map(book => {
book.words = shallowReactive(book.words)
book.articles = shallowReactive(book.articles)
book.statistics = shallowReactive(book.statistics)
})
obj.article.bookList.map(book => {
book.words = shallowReactive(book.words)
book.articles = shallowReactive(book.articles)
book.statistics = shallowReactive(book.statistics)
})
this.$patch(obj)
},
async init() {
return new Promise(async resolve => {
try {
let configStr: string = await get(SAVE_DICT_KEY.key)
let data = checkAndUpgradeSaveDict(configStr)
if (AppEnv.IS_OFFICIAL) {
let r = await dictListVersion()
if (r.success) {
data.dictListVersion = r.data
}
}
if (AppEnv.CAN_REQUEST) {
let res = await myDictList()
if (res.success) {
//只保留未同步的
data.word.bookList = data.word.bookList.filter(v => !v.sync)
data.article.bookList = data.article.bookList.filter(v => !v.sync)
//这里看看是否要 shallowReactive
Object.assign(data, res.data)
}
}
console.log('data', data)
this.setState(data)
} catch (e) {
console.error('读取本地dict数据失败', e)
}
resolve(true)
})
},
//改变词典
async changeDict(val: Dict) {
if (AppEnv.CAN_REQUEST) {
let r = await add2MyDict({
id: val.id,
perDayStudyNumber: val.perDayStudyNumber,
lastLearnIndex: val.lastLearnIndex,
complete: val.complete,
})
if (!r.success) return Toast.error(r.msg)
else val.userDictId = r.data
}
//把其他的词典的单词数据都删掉,全保存在内存里太卡了
this.word.bookList.slice(3).map(v => {
if (!v.custom) {
v.words = shallowReactive([])
}
})
let rIndex = this.word.bookList.findIndex((v: Dict) => v.id === val.id)
if (val.words.length < val.perDayStudyNumber) {
val.perDayStudyNumber = val.words.length
}
if (rIndex > -1) {
this.word.studyIndex = rIndex
this.word.bookList[this.word.studyIndex].words = shallowReactive(val.words)
this.word.bookList[this.word.studyIndex].perDayStudyNumber = val.perDayStudyNumber
this.word.bookList[this.word.studyIndex].lastLearnIndex = val.lastLearnIndex
this.word.bookList[this.word.studyIndex].userDictId = val.userDictId
} else {
this.word.bookList.push(getDefaultDict(val))
this.word.studyIndex = this.word.bookList.length - 1
}
},
//改变书籍
async changeBook(val: Dict) {
if (AppEnv.CAN_REQUEST) {
let r = await add2MyDict({
id: val.id,
perDayStudyNumber: val.perDayStudyNumber,
lastLearnIndex: val.lastLearnIndex,
complete: val.complete,
})
if (!r.success) {
return Toast.error(r.msg)
}
}
//把其他的书籍里面的文章数据都删掉,全保存在内存里太卡了
this.article.bookList.slice(1).map(v => {
if (!v.custom) {
v.articles = shallowReactive([])
}
})
let rIndex = this.article.bookList.findIndex((v: Dict) => v.id === val.id)
if (rIndex > -1) {
this.article.studyIndex = rIndex
//不要整个等于,不然统计没了
// this.article.bookList[this.article.studyIndex] = getDefaultDict(val)
this.article.bookList[this.article.studyIndex].articles = shallowReactive(val.articles)
this.article.bookList[this.article.studyIndex].cover = val.cover
this.article.bookList[this.article.studyIndex].name = val.name
this.article.bookList[this.article.studyIndex].description = val.description
} else {
this.article.bookList.push(getDefaultDict(val))
this.article.studyIndex = this.article.bookList.length - 1
}
},
},
})

View File

@@ -97,7 +97,9 @@ export interface Statistics {
export enum Sort {
normal = 0,
random = 1,
reverse = 2
reverse = 2,
reverseAll = 3,
randomAll = 4,
}
export enum ShortcutKey {