This commit is contained in:
zyronon
2024-06-09 02:17:28 +08:00
parent 164dac8992
commit 5181d612b9
7 changed files with 4591 additions and 4918 deletions

8637
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
<script setup lang="tsx">
import {useSettingStore} from "@/stores/setting.ts";
import {nextTick} from "vue";
import {nextTick, useSlots} from "vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {Sort} from "@/types.ts";
import MiniDialog from "@/pages/pc/components/dialog/MiniDialog.vue";
@@ -69,7 +69,7 @@ let currentList = $computed({
})
let selectIds = $ref([])
let selectAll = $computed(()=>{
let selectAll = $computed(() => {
return !!selectIds.length
})
@@ -104,104 +104,124 @@ function sort(type: Sort) {
list.value = shuffle(cloneDeep(list.value))
}
}
const s = useSlots()
console.log('s', s)
defineRender(
() => {
const d = (item) => <el-checkbox
modelValue={selectIds.includes(item.id)}
onChange={() => toggleSelect(item)}
size="large"/>
return (
<div class="flex flex-col gap-3">
<div class="">
{
showSearchInput ? (
<div
class="flex gap-2"
>
<Input
modelValue={searchKey}
onUpdate:model-value={e => searchKey = e}
class="flex-1"/>
<BaseButton onClick={() => showSearchInput = false}>取消</BaseButton>
</div>
) : (
<div class="flex justify-between " v-else>
<el-checkbox
onClick={() => toggleSelectAll()}
modelValue={selectAll}
size="large"/>
<div class="flex gap-2 relative">
{
selectIds.length ? <BaseIcon
onClick={emit('del')}
class="del"
title="删除"
icon="solar:trash-bin-minimalistic-linear"/> : null
}
<BaseIcon
onClick={emit('add')}
icon="fluent:add-20-filled"
title="添加单词"/>
<BaseIcon
title="改变顺序"
icon="icon-park-outline:sort-two"
onClick={() => showSortDialog = !showSortDialog}
/>
<BaseIcon
onClick={() => showSearchInput = !showSearchInput}
title="搜索"
icon="fluent:search-24-regular"/>
<MiniDialog
modelValue={showSortDialog}
onUpdate:model-value={e => showSortDialog = e}
style="width: 8rem;"
>
<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>
</MiniDialog>
</div>
</div>
)
}
</div>
<div class="flex-1 overflow-auto"
ref="listRef">
{
currentList.map((item, index) => {
return (
<div class="list-item-wrapper"
key={item.id}
>
<div class="common-list-item"
>
<div class="left">
{s.default({checkbox: d, item})}
<div class="title-wrapper">
<div class="item-title">
<span class="word">{item.word}</span>
<span class="phonetic">{item.phonetic0}</span>
<VolumeIcon class="volume"></VolumeIcon>
</div>
<div class="item-sub-title">
</div>
</div>
</div>
<div class="right">
<slot name="suffix"
item={item} index={index}>
</slot>
</div>
</div>
</div>
)
})
}
</div>
<div class="flex justify-end">
<el-pagination background
currentPage={pageNo}
onUpdate:current-page={(e) => pageNo = e}
pageSize={pageSize}
onUpdate:page-size={(e) => pageSize = e}
layout="prev, pager, next"
total={list.value.length}/>
</div>
</div>
)
}
)
</script>
<template>
<div class="flex flex-col gap-3">
<div class="">
<div
v-if="showSearchInput"
class="flex gap-2"
>
<Input v-model="searchKey"
class="flex-1"/>
<BaseButton @click="showSearchInput = false">取消</BaseButton>
</div>
<div class="flex justify-between " v-else>
<el-checkbox
@click="toggleSelectAll"
:model-value="selectAll"
size="large"/>
<div class="flex gap-2 relative">
<BaseIcon
v-if="selectIds.length"
@click="emit('del')"
class="del"
title="删除"
icon="solar:trash-bin-minimalistic-linear"/>
<BaseIcon
@click="emit('add')"
icon="fluent:add-20-filled"
title="添加单词"/>
<BaseIcon
title="改变顺序"
icon="icon-park-outline:sort-two"
@click="showSortDialog = !showSortDialog"
/>
<BaseIcon
@click="showSearchInput = !showSearchInput"
title="搜索"
icon="fluent:search-24-regular"/>
<MiniDialog
v-model="showSortDialog"
style="width: 8rem;"
>
<div class="mini-row-title">
列表顺序设置
</div>
<div class="mini-row">
<BaseButton size="small" @click="sort(Sort.reverse)">翻转</BaseButton>
<BaseButton size="small" @click="sort(Sort.random)">随机</BaseButton>
</div>
</MiniDialog>
</div>
</div>
</div>
<div
class="flex-1 overflow-auto"
ref="listRef">
<div class="list-item-wrapper"
v-for="(item,index) in currentList"
:key="item.id"
>
<div class="common-list-item"
:class="{
active:itemIsActive(item,index),
border:showBorder
}"
@click="emit('click',{item,index})"
>
<div class="left">
<el-checkbox
:model-value="selectIds.includes(item.id)"
@change="toggleSelect(item)"
size="large"/>
<div class="title-wrapper">
<div class="item-title">
<span class="word">{{ item.word }}</span>
<span class="phonetic">{{ item.phonetic0 }}</span>
<VolumeIcon class="volume"></VolumeIcon>
</div>
<div class="item-sub-title">
<div v-for="v in item.trans">{{ (v.pos ? v.pos + '.' : '') + (v.cn || v.en) }}</div>
</div>
</div>
</div>
<div class="right">
<slot name="suffix" :item="item" :index="index"></slot>
</div>
</div>
</div>
</div>
<div class="flex justify-end">
<el-pagination background
v-model:current-page="pageNo"
v-model:page-size="pageSize"
layout="prev, pager, next" :total="list.length"/>
</div>
</div>
</template>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,207 @@
<script setup lang="ts">
import {useSettingStore} from "@/stores/setting.ts";
import {nextTick} from "vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {Sort} from "@/types.ts";
import MiniDialog from "@/pages/pc/components/dialog/MiniDialog.vue";
import BaseIcon from "@/components/BaseIcon.vue";
import BaseButton from "@/components/BaseButton.vue";
import {cloneDeep, reverse, shuffle} from "lodash-es";
import Input from "@/pages/pc/components/Input.vue";
let list = defineModel('list')
const props = withDefaults(defineProps<{
activeIndex?: number,
activeId?: string,
isActive?: boolean
showBorder?: boolean
}>(), {
activeIndex: -1,
activeId: '',
isActive: false,
showBorder: false,
})
const emit = defineEmits<{
click: [val: {
item: any,
index: number
}],
}>()
const settingStore = useSettingStore()
const listRef: any = $ref()
function scrollToBottom() {
nextTick(() => {
listRef?.scrollTo(0, listRef.scrollHeight)
})
}
function scrollToItem(index: number) {
nextTick(() => {
listRef?.children[index]?.scrollIntoView({block: 'center', behavior: 'smooth'})
})
}
function itemIsActive(item: any, index: number) {
return props.activeId ?
props.activeId === item.id
: props.activeIndex === index
}
defineExpose({scrollToBottom, scrollToItem})
let pageNo = $ref(1)
let pageSize = $ref(50)
let currentList = $computed({
get() {
if (searchKey) {
return list.value.filter(v => v.word.includes(searchKey))
}
return list.value.slice((pageNo - 1) * pageSize, (pageNo - 1) * pageSize + pageSize)
},
set(v) {
list.value = v
}
})
let selectIds = $ref([])
let selectAll = $computed(()=>{
return !!selectIds.length
})
function toggleSelect(item) {
let rIndex = selectIds.findIndex(v => v === item.id)
if (rIndex > -1) {
selectIds.splice(rIndex, 1)
} else {
selectIds.push(item.id)
}
}
function toggleSelectAll() {
if (selectAll) {
selectIds = []
} else {
selectIds = currentList.map(v => v.id)
}
}
let searchKey = $ref('')
let showSortDialog = $ref(false)
let showSearchInput = $ref(false)
function sort(type: Sort) {
if (type === Sort.reverse) {
ElMessage.success('已翻转排序')
list.value = reverse(cloneDeep(list.value))
}
if (type === Sort.random) {
ElMessage.success('已随机排序')
list.value = shuffle(cloneDeep(list.value))
}
}
</script>
<template>
<div class="flex flex-col gap-3">
<div class="">
<div
v-if="showSearchInput"
class="flex gap-2"
>
<Input v-model="searchKey"
class="flex-1"/>
<BaseButton @click="showSearchInput = false">取消</BaseButton>
</div>
<div class="flex justify-between " v-else>
<el-checkbox
@click="toggleSelectAll"
:model-value="selectAll"
size="large"/>
<div class="flex gap-2 relative">
<BaseIcon
v-if="selectIds.length"
@click="emit('del')"
class="del"
title="删除"
icon="solar:trash-bin-minimalistic-linear"/>
<BaseIcon
@click="emit('add')"
icon="fluent:add-20-filled"
title="添加单词"/>
<BaseIcon
title="改变顺序"
icon="icon-park-outline:sort-two"
@click="showSortDialog = !showSortDialog"
/>
<BaseIcon
@click="showSearchInput = !showSearchInput"
title="搜索"
icon="fluent:search-24-regular"/>
<MiniDialog
v-model="showSortDialog"
style="width: 8rem;"
>
<div class="mini-row-title">
列表顺序设置
</div>
<div class="mini-row">
<BaseButton size="small" @click="sort(Sort.reverse)">翻转</BaseButton>
<BaseButton size="small" @click="sort(Sort.random)">随机</BaseButton>
</div>
</MiniDialog>
</div>
</div>
</div>
<div
class="flex-1 overflow-auto"
ref="listRef">
<div class="list-item-wrapper"
v-for="(item,index) in currentList"
:key="item.id"
>
<div class="common-list-item"
:class="{
active:itemIsActive(item,index),
border:showBorder
}"
@click="emit('click',{item,index})"
>
<div class="left">
<el-checkbox
:model-value="selectIds.includes(item.id)"
@change="toggleSelect(item)"
size="large"/>
<div class="title-wrapper">
<div class="item-title">
<span class="word">{{ item.word }}</span>
<span class="phonetic">{{ item.phonetic0 }}</span>
<VolumeIcon class="volume"></VolumeIcon>
</div>
<div class="item-sub-title">
<div v-for="v in item.trans">{{ (v.pos ? v.pos + '.' : '') + (v.cn || v.en) }}</div>
</div>
</div>
</div>
<div class="right">
<slot name="suffix" :item="item" :index="index"></slot>
</div>
</div>
</div>
</div>
<div class="flex justify-end">
<el-pagination background
v-model:current-page="pageNo"
v-model:page-size="pageSize"
layout="prev, pager, next" :total="list.length"/>
</div>
</div>
</template>
<style scoped lang="scss">
</style>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="tsx">
import BasePage from "@/pages/pc/components/BasePage.vue";
import {onMounted, reactive} from "vue";
@@ -6,11 +6,9 @@ import {useRoute} from "vue-router";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {useBaseStore} from "@/stores/base.ts";
import {assign, cloneDeep} from "lodash-es";
import {Word} from "@/types.ts";
import {nanoid} from "nanoid";
import BaseIcon from "@/components/BaseIcon.vue";
import {_checkDictWords, useNav} from "@/utils";
import {FormInstance, FormRules} from "element-plus";
import BaseTable from "@/pages/pc/components/BaseTable.vue";
const runtimeStore = useRuntimeStore()
@@ -29,9 +27,11 @@ let list = $computed({
onMounted(() => {
switch (Number(route.query.type)) {
case -1:
runtimeStore.editDict = cloneDeep(runtimeStore.routeData)
_checkDictWords(runtimeStore.editDict)
break
if (runtimeStore.routeData) {
runtimeStore.editDict = cloneDeep(runtimeStore.routeData)
_checkDictWords(runtimeStore.editDict)
}
// break
case 0:
runtimeStore.editDict = cloneDeep(store.collectWord)
break
@@ -148,76 +148,92 @@ function closeWordForm() {
wordForm = cloneDeep(DefaultFormWord)
}
</script>
<template>
<BasePage>
<header class="flex gap-4 mb-2 items-center">
<BaseIcon @click="back" icon="octicon:arrow-left-24" width="20"/>
<div class="left">
<div class="top">
<div class="text-xl">
{{ runtimeStore.editDict.name }}
</div>
</div>
<div class="desc" v-if="runtimeStore.editDict.description">{{ runtimeStore.editDict.description }}</div>
</div>
</header>
<div class="flex h-140">
<div class="w-1/2">
<BaseTable
class="h-full"
ref="listRef"
v-model:list="list">
<template v-slot:suffix="{ item, index }">
<BaseIcon
class="del"
@click="editWord(item)"
title="编辑"
icon="tabler:edit"/>
<BaseIcon
class="del"
@click="del({item,index})"
title="删除"
icon="solar:trash-bin-minimalistic-linear"/>
</template>
</BaseTable>
</div>
<div class="add w-1/2" v-if="wordFormData.type">
<div class="common-title">
{{ wordFormData.type === FormMode.Add ? '添加' : '修改' }}单词
</div>
<el-form
class="form"
ref="wordFormRef"
:rules="wordRules"
:model="wordForm"
label-width="6rem">
<el-form-item label="单词" prop="word">
<el-input v-model="wordForm.word"/>
</el-form-item>
<el-form-item label="翻译">
<el-input v-model="wordForm.trans"
placeholder="多个翻译请换行"
:autosize="{ minRows: 2, maxRows: 6 }"
type="textarea"/>
</el-form-item>
<el-form-item label="音标/发音①">
<el-input v-model="wordForm.phonetic0"/>
</el-form-item>
<el-form-item label="音标/发音②">
<el-input v-model="wordForm.phonetic1"/>
</el-form-item>
<div class="flex-center">
<el-button @click="closeWordForm">关闭</el-button>
<el-button type="primary" @click="onSubmitWord">保存</el-button>
</div>
</el-form>
</div>
defineRender(() => {
let d = (i) => {
console.log('i', i)
return <div>
{i.checkbox(i.item)}
</div>
</BasePage>
</template>
}
return (
<BasePage>
<header class="flex gap-4 mb-2 items-center">
<BaseIcon onClick={back} icon="octicon:arrow-left-24" width="20"/>
<div class="left">
<div class="top">
<div class="text-xl">
{runtimeStore.editDict.name}
</div>
</div>
{
runtimeStore.editDict.description ?
<div class="desc">{runtimeStore.editDict.description}</div> : null
}
</div>
</header>
<div class="flex h-120">
<div class="w-1/2">
<BaseTable
class="h-full"
list={list}
>
{d}
</BaseTable>
</div>
{
wordFormData.type ? (
<div class="add w-1/2">
<div class="common-title">
{wordFormData.type === FormMode.Add ? '添加' : '修改'}单词
</div>
<el-form
class="form"
ref="wordFormRef"
rules={wordRules}
model={wordForm}
label-width="6rem">
<el-form-item label="单词" prop="word">
<el-input
modelValue={wordForm.word}
onUpdate:model-value={e => wordForm.word = e}
/>
</el-form-item>
<el-form-item label="翻译">
<el-input
modelValue={wordForm.trans}
onUpdate:model-value={e => wordForm.trans = e}
placeholder="多个翻译请换行"
autosize={{minRows: 2, maxRows: 6}}
type="textarea"/>
</el-form-item>
<el-form-item label="音标/发音①">
<el-input
modelValue={wordForm.phonetic0}
onUpdate:model-value={e => wordForm.phonetic0 = e}
/>
</el-form-item>
<el-form-item label="音标/发音②">
<el-input
modelValue={wordForm.phonetic1}
onUpdate:model-value={e => wordForm.phonetic1 = e}/>
</el-form-item>
<div class="flex-center">
<el-button
onClick={closeWordForm}>关闭
</el-button>
<el-button type="primary"
onClick={onSubmitWord}>保存
</el-button>
</div>
</el-form>
</div>
) : null
}
</div>
</BasePage>
)
})
</script>
<style scoped lang="scss">

View File

@@ -0,0 +1,229 @@
<script setup lang="ts">
import BasePage from "@/pages/pc/components/BasePage.vue";
import {onMounted, reactive} from "vue";
import {useRoute} from "vue-router";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {useBaseStore} from "@/stores/base.ts";
import {assign, cloneDeep} from "lodash-es";
import {Word} from "@/types.ts";
import {nanoid} from "nanoid";
import BaseIcon from "@/components/BaseIcon.vue";
import {_checkDictWords, useNav} from "@/utils";
import {FormInstance, FormRules} from "element-plus";
import BaseTable from "@/pages/pc/components/BaseTable.vue";
const runtimeStore = useRuntimeStore()
const store = useBaseStore()
const route = useRoute()
let list = $computed({
get() {
return runtimeStore.editDict.words
},
set(v) {
runtimeStore.editDict.words = v
}
})
onMounted(() => {
switch (Number(route.query.type)) {
case -1:
runtimeStore.editDict = cloneDeep(runtimeStore.routeData)
_checkDictWords(runtimeStore.editDict)
break
case 0:
runtimeStore.editDict = cloneDeep(store.collectWord)
break
case 1:
runtimeStore.editDict = cloneDeep(store.wrong)
break
case 2:
runtimeStore.editDict = cloneDeep(store.simple)
break
case 3:
runtimeStore.editDict = cloneDeep(store.master)
break
default:
break
}
})
const {back} = useNav()
let wordFormData = $ref({
where: '',
type: '',
id: '',
index: 0
})
enum FormMode {
None = '',
Add = 'Add',
Edit = 'Edit',
}
const DefaultFormWord = {
word: '',
phonetic0: '',
phonetic1: '',
trans: '',
}
let wordForm = $ref(cloneDeep(DefaultFormWord))
const wordFormRef = $ref<FormInstance>()
const wordRules = reactive<FormRules>({
name: [
{required: true, message: '请输入单词', trigger: 'blur'},
{max: 30, message: '名称不能超过30个字符', trigger: 'blur'},
],
})
//TODO trans结构变了
async function onSubmitWord() {
await wordFormRef.validate((valid, fields) => {
if (valid) {
let data: any = cloneDeep(wordForm)
if (data.trans) {
data.trans = data.trans.split('\n');
} else {
data.trans = []
}
if (wordFormData.type === FormMode.Add) {
data.id = nanoid(6)
data.checked = false
let r = list.find(v => v.word === wordForm.word)
// if (r) return ElMessage.warning('已有相同名称单词!')
// else list.push(data)
list.push(data)
ElMessage.success('添加成功')
wordForm = cloneDeep(DefaultFormWord)
// setTimeout(wordListRef?.scrollToBottom, 100)
} else {
let r = list.find(v => v.id === wordFormData.id)
if (r) assign(r, data)
r = list.find(v => v.id === wordFormData.id)
if (r) assign(r, data)
ElMessage.success('修改成功')
}
} else {
ElMessage.warning('请填写完整')
}
})
}
function delWord(val: {
item: Word
}) {
let rIndex2 = list.findIndex(v => v.id === val.item.id)
if (rIndex2 > -1) {
list.splice(rIndex2, 1)
}
if (wordFormData.type === FormMode.Edit && wordForm.word === val.item.word) {
closeWordForm()
}
}
function batchDelWord() {
console.log('multipleSelection', multipleSelection)
multipleSelection.map(v => delWord({item: v}))
}
function editWord(word: Word,) {
wordFormData.type = FormMode.Edit
wordFormData.id = word.id
wordForm.word = word.word
wordForm.phonetic1 = word.phonetic1
wordForm.phonetic0 = word.phonetic0
wordForm.trans = word.trans.join('\n')
}
function addWord() {
// setTimeout(wordListRef?.scrollToBottom, 100)
wordFormData.type = FormMode.Add
wordForm = cloneDeep(DefaultFormWord)
}
function closeWordForm() {
wordFormData.type = FormMode.None
wordForm = cloneDeep(DefaultFormWord)
}
</script>
<template>
<BasePage>
<header class="flex gap-4 mb-2 items-center">
<BaseIcon @click="back" icon="octicon:arrow-left-24" width="20"/>
<div class="left">
<div class="top">
<div class="text-xl">
{{ runtimeStore.editDict.name }}
</div>
</div>
<div class="desc" v-if="runtimeStore.editDict.description">{{ runtimeStore.editDict.description }}</div>
</div>
</header>
<div class="flex h-140">
<div class="w-1/2">
<BaseTable
class="h-full"
ref="listRef"
v-model:list="list">
<template v-slot="{item}">
<span>123</span>
<span>{{item}}</span>
</template>
<template v-slot:suffix="{ item, index }">
<span>1</span>
<BaseIcon
class="del"
@click="editWord(item)"
title="编辑"
icon="tabler:edit"/>
<BaseIcon
class="del"
@click="del({item,index})"
title="删除"
icon="solar:trash-bin-minimalistic-linear"/>
</template>
</BaseTable>
</div>
<div class="add w-1/2" v-if="wordFormData.type">
<div class="common-title">
{{ wordFormData.type === FormMode.Add ? '添加' : '修改' }}单词
</div>
<el-form
class="form"
ref="wordFormRef"
:rules="wordRules"
:model="wordForm"
label-width="6rem">
<el-form-item label="单词" prop="word">
<el-input v-model="wordForm.word"/>
</el-form-item>
<el-form-item label="翻译">
<el-input v-model="wordForm.trans"
placeholder="多个翻译请换行"
:autosize="{ minRows: 2, maxRows: 6 }"
type="textarea"/>
</el-form-item>
<el-form-item label="音标/发音①">
<el-input v-model="wordForm.phonetic0"/>
</el-form-item>
<el-form-item label="音标/发音②">
<el-input v-model="wordForm.phonetic1"/>
</el-form-item>
<div class="flex-center">
<el-button @click="closeWordForm">关闭</el-button>
<el-button type="primary" @click="onSubmitWord">保存</el-button>
</div>
</el-form>
</div>
</div>
</BasePage>
</template>
<style scoped lang="scss">
</style>

View File

@@ -128,30 +128,6 @@ function changePerDayStudyNumber() {
</div>
</div>
<div class="card flex flex-col">
<div class="title">
我的词典
</div>
<div class="grid grid-cols-6 gap-4 mt-4">
<div class="my-dict" @click="nav('edit-word-dict',{type:0})">
<span>收藏</span>
<div class="absolute bottom-4 right-4">{{ store.collectWord.words.length }}个词</div>
</div>
<div class="my-dict" @click="nav('edit-word-dict',{type:1})">
<span>错词本</span>
<div class="absolute bottom-4 right-4">{{ store.wrong.words.length }}个词</div>
</div>
<div class="my-dict" @click="nav('edit-word-dict',{type:2})">
<span>简单词</span>
<div class="absolute bottom-4 right-4">{{ store.simple.words.length }}个词</div>
</div>
<div class="my-dict" @click="nav('edit-word-dict',{type:3})">
<span>已掌握</span>
<div class="absolute bottom-4 right-4">{{ store.master.words.length }}个词</div>
</div>
</div>
</div>
<div class="card" v-if="otherWordDictList.length">
<div class="flex justify-between">
<div class="title">
@@ -181,6 +157,30 @@ function changePerDayStudyNumber() {
</div>
</div>
<div class="card flex flex-col">
<div class="title">
我的词典
</div>
<div class="grid grid-cols-6 gap-4 mt-4">
<div class="my-dict" @click="nav('edit-word-dict',{type:0})">
<span>收藏</span>
<div class="absolute bottom-4 right-4">{{ store.collectWord.words.length }}个词</div>
</div>
<div class="my-dict" @click="nav('edit-word-dict',{type:1})">
<span>错词本</span>
<div class="absolute bottom-4 right-4">{{ store.wrong.words.length }}个词</div>
</div>
<div class="my-dict" @click="nav('edit-word-dict',{type:2})">
<span>简单词</span>
<div class="absolute bottom-4 right-4">{{ store.simple.words.length }}个词</div>
</div>
<div class="my-dict" @click="nav('edit-word-dict',{type:3})">
<span>已掌握</span>
<div class="absolute bottom-4 right-4">{{ store.master.words.length }}个词</div>
</div>
</div>
</div>
<div class="card">
<div class="title">
已学习 <span class="text-3xl">159</span>

View File

@@ -39,6 +39,7 @@ export const DefaultBaseState = (): BaseState => ({
index: 1,
name: '收藏', type: DictType.collectWord, words: [
{
"id": "pharmacy",
"word": "pharmacy",
"trans": [
{
@@ -49,6 +50,7 @@ export const DefaultBaseState = (): BaseState => ({
"phonetic1": "ˈfɑ:rməsi"
},
{
"id": "foregone",
"word": "foregone",
"trans": [
{