feat:fix dict list
This commit is contained in:
@@ -95,8 +95,10 @@ function startStudy() {
|
||||
<div class="book"
|
||||
v-for="dict in store.article.bookList"
|
||||
@click="getBookDetail2(dict)">
|
||||
<div class="name">{{ dict.name }}</div>
|
||||
<div class="desc">{{ dict.description }}</div>
|
||||
<div>
|
||||
<div class="name">{{ dict.name }}</div>
|
||||
<div class="desc">{{ dict.description }}</div>
|
||||
</div>
|
||||
<div class="absolute bottom-4 right-4">{{ dict.length }}篇</div>
|
||||
</div>
|
||||
<div class="book" @click="showAddChooseDialog = true">
|
||||
@@ -118,8 +120,10 @@ function startStudy() {
|
||||
<div class="book"
|
||||
v-for="dict in enArticle"
|
||||
@click="getBookDetail(dict)">
|
||||
<div class="name">{{ dict.name }}</div>
|
||||
<div class="desc">{{ dict.description }}</div>
|
||||
<div class="top">
|
||||
<div class="name">{{ dict.name }}</div>
|
||||
<div class="desc">{{ dict.description }}</div>
|
||||
</div>
|
||||
<div class="absolute bottom-4 right-4">{{ dict.length }}篇</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import EditBook from "@/pages/pc/article/components/EditBook.vue";
|
||||
import {computed, onMounted} from "vue";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const base = useBaseStore()
|
||||
@@ -53,7 +54,12 @@ const showBookDetail = computed(() => {
|
||||
onMounted(() => {
|
||||
if (route.query?.isAdd) {
|
||||
isAdd = true
|
||||
}else {
|
||||
if (!runtimeStore.editDict.id) {
|
||||
router.push("/")
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
function formClose() {
|
||||
@@ -69,7 +75,7 @@ function formClose() {
|
||||
<BackIcon class="z-2" @click="$router.back"/>
|
||||
<div class="absolute text-2xl text-align-center w-full">{{ runtimeStore.editDict.name }}</div>
|
||||
<div class="flex gap-2">
|
||||
<BaseButton type="info" @click="isEdit = true">编辑信息</BaseButton>
|
||||
<BaseButton type="info" @click="isEdit = true">编辑</BaseButton>
|
||||
<BaseButton type="info" @click="router.push('batch-edit-article')">文章管理</BaseButton>
|
||||
<BaseButton @click="addMyBookList">学习</BaseButton>
|
||||
</div>
|
||||
@@ -109,11 +115,20 @@ function formClose() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="center" v-else>
|
||||
<div class="w-1/2">
|
||||
<EditBook :is-add="isAdd"
|
||||
@close="formClose"
|
||||
@submit="isEdit = isAdd = false"
|
||||
<div class="card mb-0 h-[95vh]" v-else>
|
||||
<div class="flex justify-between items-center relative">
|
||||
<BackIcon class="z-2" @click="isAdd ? $router.back():(isEdit = false)"/>
|
||||
<div class="absolute text-2xl text-align-center w-full">{{
|
||||
runtimeStore.editDict.id ? '修改' : '添加'
|
||||
}}书籍
|
||||
</div>
|
||||
</div>
|
||||
<div class="center">
|
||||
<EditBook
|
||||
:is-add="isAdd"
|
||||
:is-book="true"
|
||||
@close="formClose"
|
||||
@submit="isEdit = isAdd = false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,8 @@ import {useBaseStore} from "@/stores/base.ts";
|
||||
import {syncMyDictList} from "@/hooks/dict.ts";
|
||||
|
||||
const props = defineProps<{
|
||||
isAdd: boolean
|
||||
isAdd: boolean,
|
||||
isBook: boolean
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
submit: []
|
||||
@@ -44,28 +45,29 @@ async function onSubmit() {
|
||||
...getDefaultDict(),
|
||||
...dictForm,
|
||||
})
|
||||
let source = [store.article, store.word][props.isBook ? 0 : 1]
|
||||
//任意修改,都将其变为自定义词典
|
||||
data.isCustom = true
|
||||
|
||||
if (props.isAdd) {
|
||||
data.id = 'custom-dict-' + Date.now()
|
||||
//TODO 允许同名?
|
||||
if (store.article.bookList.find(v => v.name === data.name)) {
|
||||
if (source.bookList.find(v => v.name === data.name)) {
|
||||
return ElMessage.warning('已有相同名称书籍!')
|
||||
} else {
|
||||
store.article.bookList.push(data)
|
||||
source.bookList.push(data)
|
||||
runtimeStore.editDict = data
|
||||
emit('submit')
|
||||
ElMessage.success('添加成功')
|
||||
}
|
||||
} else {
|
||||
let rIndex = store.article.bookList.findIndex(v => v.id === data.id)
|
||||
let rIndex = source.bookList.findIndex(v => v.id === data.id)
|
||||
if (rIndex > -1) {
|
||||
store.article.bookList[rIndex] = cloneDeep(data)
|
||||
source.bookList[rIndex] = cloneDeep(data)
|
||||
runtimeStore.editDict = cloneDeep(data)
|
||||
emit('submit')
|
||||
ElMessage.success('修改成功')
|
||||
}else {
|
||||
} else {
|
||||
ElMessage.warning('修改失败')
|
||||
}
|
||||
}
|
||||
@@ -85,61 +87,43 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="edit-dict">
|
||||
<div class="wrapper">
|
||||
<div class="common-title">{{ dictForm.id ? '修改' : '添加' }}书籍</div>
|
||||
<el-form
|
||||
ref="dictFormRef"
|
||||
:rules="dictRules"
|
||||
:model="dictForm"
|
||||
label-width="8rem">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="dictForm.name"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="dictForm.description" type="textarea"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="原文语言">
|
||||
<el-select v-model="dictForm.language" placeholder="请选择选项">
|
||||
<el-option label="英语" value="en"/>
|
||||
<el-option label="德语" value="de"/>
|
||||
<el-option label="日语" value="ja"/>
|
||||
<el-option label="代码" value="code"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="译文语言">
|
||||
<el-select v-model="dictForm.translateLanguage" placeholder="请选择选项">
|
||||
<!-- <el-option label="通用" value="common"/>-->
|
||||
<el-option label="中文" value="zh-CN"/>
|
||||
<el-option label="英语" value="en"/>
|
||||
<el-option label="德语" value="de"/>
|
||||
<el-option label="日语" value="ja"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div class="center">
|
||||
<el-button @click="emit('close')">关闭</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="w-120 mt-4">
|
||||
<el-form
|
||||
ref="dictFormRef"
|
||||
:rules="dictRules"
|
||||
:model="dictForm"
|
||||
label-width="8rem">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="dictForm.name"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="dictForm.description" type="textarea"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="原文语言">
|
||||
<el-select v-model="dictForm.language" placeholder="请选择选项">
|
||||
<el-option label="英语" value="en"/>
|
||||
<el-option label="德语" value="de"/>
|
||||
<el-option label="日语" value="ja"/>
|
||||
<el-option label="代码" value="code"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="译文语言">
|
||||
<el-select v-model="dictForm.translateLanguage" placeholder="请选择选项">
|
||||
<el-option label="中文" value="zh-CN"/>
|
||||
<el-option label="英语" value="en"/>
|
||||
<el-option label="德语" value="de"/>
|
||||
<el-option label="日语" value="ja"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div class="center">
|
||||
<el-button @click="emit('close')">关闭</el-button>
|
||||
<el-button type="primary" @click="onSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.edit-dict {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.wrapper {
|
||||
width: 80rem;
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="tsx">
|
||||
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {nextTick, useSlots} from "vue";
|
||||
import {Sort} from "@/types.ts";
|
||||
import MiniDialog from "@/pages/pc/components/dialog/MiniDialog.vue";
|
||||
@@ -101,6 +100,7 @@ function sort(type: Sort) {
|
||||
ElMessage.success('已随机排序')
|
||||
list.value = shuffle(cloneDeep(list.value))
|
||||
}
|
||||
showSortDialog = false
|
||||
}
|
||||
|
||||
function handleBatchDel() {
|
||||
@@ -178,7 +178,7 @@ defineRender(
|
||||
icon="fluent:search-24-regular"/>
|
||||
<MiniDialog
|
||||
modelValue={showSortDialog}
|
||||
onUpdate:model-value={e => showSortDialog = e}
|
||||
onUpdate:modelValue={e => showSortDialog = e}
|
||||
style="width: 8rem;"
|
||||
>
|
||||
<div class="mini-row-title">
|
||||
|
||||
@@ -6,7 +6,7 @@ import {useDisableEventListener, useWindowClick} from "@/hooks/event.ts";
|
||||
|
||||
defineProps<{
|
||||
modelValue: string
|
||||
placeholder: string
|
||||
placeholder?: string
|
||||
autofocus?: boolean
|
||||
}>()
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ $bg-color: rgb(226, 226, 226);
|
||||
.text {
|
||||
color: var(--color-font-1);
|
||||
text-align: start;
|
||||
font-size: .9rem;
|
||||
font-size: 1rem;
|
||||
width: 9rem;
|
||||
min-width: 9rem;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ $bg-color: rgb(226, 226, 226);
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: .7rem;
|
||||
font-size: .7rem;
|
||||
font-size: .9rem;
|
||||
|
||||
div {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<template>
|
||||
<div class="round">
|
||||
<svg height="100%" width="100%">
|
||||
<circle class="circle-full"
|
||||
cx="3rem"
|
||||
cy="3rem"
|
||||
r="2.6rem"
|
||||
fill="none"
|
||||
stroke-width=".4rem"
|
||||
stroke-linecap="round"></circle>
|
||||
<circle v-if="props.percentage" ref="circleEl"
|
||||
class="circle-detail"
|
||||
cx="3rem"
|
||||
cy="3rem"
|
||||
r="2.6rem"
|
||||
fill="none"
|
||||
stroke-width=".4rem"
|
||||
stroke-linecap="round"
|
||||
stroke-dasharray="0,10000"></circle>
|
||||
</svg>
|
||||
<span class="text-2xl">{{ props.value }}</span>
|
||||
<span class="desc">{{ props.desc }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {onMounted} from "vue"
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
percentage?: number,
|
||||
value: string | number,
|
||||
desc: string,
|
||||
}>(), {
|
||||
percentage: 90,
|
||||
})
|
||||
|
||||
const circleEl = $ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.percentage) {
|
||||
let circleLength = Math.floor(2 * Math.PI * 35);
|
||||
let val = Number(props.percentage.toFixed(0));
|
||||
circleEl.setAttribute("stroke-dasharray", "" + circleLength * val / 100 + "px,10000");
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
|
||||
$w: 6rem;
|
||||
$w2: calc($w / 2);
|
||||
|
||||
.round {
|
||||
font-size: 1rem;
|
||||
width: $w;
|
||||
height: $w;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
|
||||
.circle-full {
|
||||
$item-hover: rgb(75, 75, 75);
|
||||
stroke: $item-hover;
|
||||
}
|
||||
|
||||
.circle-detail {
|
||||
transform-origin: $w2 $w2;
|
||||
transform: rotate(-90deg);
|
||||
stroke: var(--color-main-active);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -8,10 +8,12 @@ const props = withDefaults(defineProps<{
|
||||
item: Word,
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
showTransPop?: boolean
|
||||
hiddenOptionIcon?: boolean
|
||||
}>(), {
|
||||
showTranslate: true,
|
||||
showWord: true,
|
||||
showTransPop: true,
|
||||
hiddenOptionIcon: false,
|
||||
})
|
||||
|
||||
@@ -34,7 +36,7 @@ const playWordAudio = usePlayWordAudio()
|
||||
<div class="item-sub-title flex flex-col gap-2" v-if="item.trans.length && showTranslate">
|
||||
<div v-for="v in item.trans">
|
||||
<el-popover
|
||||
v-if="v.cn.length > 30"
|
||||
v-if="v.cn.length > 30 && showTransPop"
|
||||
width="300"
|
||||
:content="v.pos + ' ' + v.cn"
|
||||
placement="top"
|
||||
|
||||
@@ -73,7 +73,7 @@ const {toggleTheme} = useTheme()
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 z-1">
|
||||
<div class="flex-1 z-1 relative">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
<script setup lang="tsx">
|
||||
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {computed, onMounted, reactive} from "vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {assign, cloneDeep} from "lodash-es";
|
||||
import {nanoid} from "nanoid";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {useNav} from "@/utils";
|
||||
import BaseTable from "@/pages/pc/components/BaseTable.vue";
|
||||
import WordItem from "@/pages/pc/components/WordItem.vue";
|
||||
import type {Word} from "@/types.ts";
|
||||
import type {FormInstance, FormRules} from "element-plus";
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import BackIcon from "@/components/BackIcon.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import EditBook from "@/pages/pc/article/components/EditBook.vue";
|
||||
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const base = useBaseStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
let loading = $ref(false)
|
||||
|
||||
let list = $computed({
|
||||
@@ -25,17 +33,11 @@ let list = $computed({
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
if (runtimeStore.routeData) {
|
||||
loading = true
|
||||
runtimeStore.editDict = cloneDeep(runtimeStore.routeData)
|
||||
// await _checkDictWords(runtimeStore.editDict)
|
||||
setTimeout(() => {
|
||||
loading = false
|
||||
}, 300)
|
||||
onMounted(() => {
|
||||
if (!runtimeStore.editDict.id) {
|
||||
router.push("/")
|
||||
}
|
||||
})
|
||||
const {back} = useNav()
|
||||
|
||||
let wordFormData = $ref({
|
||||
where: '',
|
||||
@@ -132,119 +134,153 @@ function closeWordForm() {
|
||||
wordForm = cloneDeep(DefaultFormWord)
|
||||
}
|
||||
|
||||
function s(ss) {
|
||||
console.log('s', ss)
|
||||
let isEdit = $ref(false)
|
||||
let isAdd = $ref(false)
|
||||
|
||||
const showBookDetail = computed(() => {
|
||||
return !(isAdd || isEdit);
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (route.query?.isAdd) {
|
||||
isAdd = true
|
||||
}
|
||||
})
|
||||
|
||||
function formClose() {
|
||||
if (isEdit) isEdit = false
|
||||
else router.back()
|
||||
}
|
||||
|
||||
function addMyBookList() {
|
||||
|
||||
}
|
||||
|
||||
defineRender(() => {
|
||||
return (
|
||||
<BasePage>
|
||||
<div className="card">
|
||||
<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}
|
||||
{
|
||||
showBookDetail.value ? <div className="card mb-0 h-[95vh] flex flex-col">
|
||||
<div class="flex justify-between items-center relative">
|
||||
<BackIcon class="z-2" onClick={() => router.back()}/>
|
||||
<div class="absolute text-2xl text-align-center w-full">{runtimeStore.editDict.name}</div>
|
||||
<div class="flex gap-2">
|
||||
<BaseButton type="info" onClick={() => isEdit = true}>编辑</BaseButton>
|
||||
<BaseButton onClick={addMyBookList}>学习</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-lg ">介绍:{runtimeStore.editDict.description}</div>
|
||||
<div class="line my-3"></div>
|
||||
|
||||
<div class="flex flex-1 overflow-hidden">
|
||||
<div class="w-4/10">
|
||||
<BaseTable
|
||||
class="h-full"
|
||||
list={list}
|
||||
loading={loading}
|
||||
onUpdate:list={e => list = e}
|
||||
del={delWord}
|
||||
batchDel={batchDel}
|
||||
add={addWord}
|
||||
>
|
||||
{
|
||||
(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="编辑"
|
||||
icon="tabler:edit"/>
|
||||
<PopConfirm title="确认删除?"
|
||||
onConfirm={() => delWord(val.item.id)}
|
||||
>
|
||||
<BaseIcon
|
||||
class="option-icon"
|
||||
title="删除"
|
||||
icon="solar:trash-bin-minimalistic-linear"/>
|
||||
</PopConfirm>
|
||||
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</WordItem>
|
||||
}
|
||||
</BaseTable>
|
||||
</div>
|
||||
{
|
||||
wordFormData.type ? (
|
||||
<div class="flex-1 ml-4">
|
||||
<div class="common-title">
|
||||
{wordFormData.type === FormMode.Add ? '添加' : '修改'}单词
|
||||
</div>
|
||||
<el-form
|
||||
className="form"
|
||||
ref="wordFormRef"
|
||||
rules={wordRules}
|
||||
model={wordForm}
|
||||
label-width="7rem">
|
||||
<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: 6, maxRows: 10}}
|
||||
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="center">
|
||||
<el-button
|
||||
onClick={closeWordForm}>关闭
|
||||
</el-button>
|
||||
<el-button type="primary"
|
||||
onClick={onSubmitWord}>保存
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
</div>
|
||||
</div> :
|
||||
<div class="card mb-0 h-[95vh]">
|
||||
<div class="flex justify-between items-center relative">
|
||||
<BackIcon class="z-2" onClick={() => isAdd ? router.back() : (isEdit = false)}/>
|
||||
<div class="absolute text-2xl 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>
|
||||
{
|
||||
runtimeStore.editDict.description ?
|
||||
<div class="desc">{runtimeStore.editDict.description}</div> : null
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
<div class="flex" style="height:calc(100vh - 8rem)">
|
||||
<div class="w-1/2">
|
||||
<BaseTable
|
||||
class="h-full"
|
||||
list={list}
|
||||
loading={loading}
|
||||
onUpdate:list={e => list = e}
|
||||
del={delWord}
|
||||
batchDel={batchDel}
|
||||
add={addWord}
|
||||
>
|
||||
{
|
||||
(val) =>
|
||||
<WordItem
|
||||
item={val.item}>
|
||||
{{
|
||||
prefix: () => val.checkbox(val.item),
|
||||
suffix: () => (
|
||||
<div class='flex flex-col'>
|
||||
<BaseIcon
|
||||
class="option-icon"
|
||||
onClick={() => editWord(val.item)}
|
||||
title="编辑"
|
||||
icon="tabler:edit"/>
|
||||
<PopConfirm title="确认删除?"
|
||||
onConfirm={() => delWord(val.item.id)}
|
||||
>
|
||||
<BaseIcon
|
||||
class="option-icon"
|
||||
title="删除"
|
||||
icon="solar:trash-bin-minimalistic-linear"/>
|
||||
</PopConfirm>
|
||||
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</WordItem>
|
||||
}
|
||||
</BaseTable>
|
||||
</div>
|
||||
{
|
||||
wordFormData.type ? (
|
||||
<div class="flex-1 ml-4">
|
||||
<div class="common-title">
|
||||
{wordFormData.type === FormMode.Add ? '添加' : '修改'}单词
|
||||
</div>
|
||||
<el-form
|
||||
className="form"
|
||||
ref="wordFormRef"
|
||||
rules={wordRules}
|
||||
model={wordForm}
|
||||
label-width="7rem">
|
||||
<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: 6, maxRows: 10}}
|
||||
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="center">
|
||||
<el-button
|
||||
onClick={closeWordForm}>关闭
|
||||
</el-button>
|
||||
<el-button type="primary"
|
||||
onClick={onSubmitWord}>保存
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</BasePage>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -62,13 +62,13 @@ function selectDict(e) {
|
||||
|
||||
async function goDictDetail2(val: Dict) {
|
||||
runtimeStore.editDict = cloneDeep(val)
|
||||
nav('edit-word-dict')
|
||||
nav('edit-word-dict', {})
|
||||
}
|
||||
|
||||
async function getBookDetail(val: DictResource) {
|
||||
let r = await getArticleBookDataByUrl(val)
|
||||
runtimeStore.editDict = cloneDeep(r)
|
||||
nav('book-detail')
|
||||
nav('book-detail', {})
|
||||
}
|
||||
|
||||
let dictListRef = $ref<any>()
|
||||
|
||||
@@ -163,7 +163,7 @@ const progress = $computed(() => {
|
||||
<RepeatSetting/>
|
||||
|
||||
<BaseIcon
|
||||
@click="emitter.emit(EventKey.openStatModal, {})"
|
||||
@click="settingStore.showPanel = !settingStore.showPanel"
|
||||
:title="`单词本(${settingStore.shortcutKeyMap[ShortcutKey.TogglePanel]})`"
|
||||
icon="tdesign:menu-unfold"/>
|
||||
</div>
|
||||
@@ -176,6 +176,7 @@ const progress = $computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
@click="emitter.emit(EventKey.openStatModal, {})"
|
||||
@click="settingStore.showPanel = !settingStore.showPanel"-->
|
||||
</template>
|
||||
|
||||
@@ -265,6 +265,7 @@ let tab = $ref(2)
|
||||
.typing-word {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
word-break: break-word;
|
||||
position: relative;
|
||||
color: var(--color-font-2);
|
||||
@@ -9,13 +9,13 @@ import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useOnKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Tooltip from "@/pages/pc/components/Tooltip.vue";
|
||||
import Typing from "@/pages/pc/components/Typing.vue";
|
||||
import Typing from "@/pages/pc/word/components/Typing.vue";
|
||||
import Panel from "@/pages/pc/components/Panel.vue";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import WordList from "@/pages/pc/components/list/WordList.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import Footer from "@/pages/pc/word/Footer.vue";
|
||||
import Footer from "@/pages/pc/word/components/Footer.vue";
|
||||
|
||||
interface IProps {
|
||||
data: {
|
||||
@@ -238,15 +238,14 @@ useEvents([
|
||||
@wrong="wordWrong"
|
||||
@complete="next"
|
||||
/>
|
||||
<Footer
|
||||
:is-simple="isWordSimple(word)"
|
||||
@toggle-simple="toggleWordSimpleWrapper"
|
||||
:is-collect="isWordCollect(word)"
|
||||
@toggle-collect="toggleWordCollect(word)"
|
||||
@skip="next(false)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Footer
|
||||
:is-simple="isWordSimple(word)"
|
||||
@toggle-simple="toggleWordSimpleWrapper"
|
||||
:is-collect="isWordCollect(word)"
|
||||
@toggle-collect="toggleWordCollect(word)"
|
||||
@skip="next(false)"
|
||||
/>
|
||||
<div class="word-panel-wrapper">
|
||||
<Panel>
|
||||
<template v-slot="{active}">
|
||||
@@ -302,21 +301,16 @@ useEvents([
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.practice-word {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: .4rem;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: var(--toolbar-width);
|
||||
}
|
||||
@@ -324,6 +318,7 @@ useEvents([
|
||||
.word-panel-wrapper {
|
||||
position: absolute;
|
||||
left: var(--panel-margin-left);
|
||||
//left: 0;
|
||||
top: .8rem;
|
||||
z-index: 1;
|
||||
height: calc(100% - 1.5rem);
|
||||
|
||||
@@ -55,8 +55,7 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
word: {
|
||||
bookList: [
|
||||
getDefaultDict({
|
||||
index: 1,
|
||||
name: '收藏', type: DictType.collectWord, words: [
|
||||
id: 'word-collect', name: '收藏', words: [
|
||||
{
|
||||
"id": "pharmacy",
|
||||
"word": "pharmacy",
|
||||
@@ -119,14 +118,10 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
"phonetic0": "ˈfɜ:nɪʃ",
|
||||
"phonetic1": "ˈfɜ:rnɪʃ"
|
||||
},
|
||||
], statistics: []
|
||||
}),
|
||||
getDefaultDict({
|
||||
index: 2, name: '错词', type: DictType.wrong, words: [], statistics: []
|
||||
}),
|
||||
getDefaultDict({
|
||||
index: 3, name: '已掌握', type: DictType.known, words: [], statistics: []
|
||||
]
|
||||
}),
|
||||
getDefaultDict({id: 'word-wrong', name: '错词'}),
|
||||
getDefaultDict({id: 'word-known', name: '已掌握'}),
|
||||
getDefaultDict({
|
||||
id: 'nce-new-2',
|
||||
name: '新概念英语(新版)-2',
|
||||
@@ -144,7 +139,7 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
},
|
||||
article: {
|
||||
bookList: [
|
||||
getDefaultDict({name: '收藏'})
|
||||
getDefaultDict({id: 'article-collect', name: '收藏'})
|
||||
],
|
||||
studyIndex: -1,
|
||||
}
|
||||
@@ -245,8 +240,11 @@ export const useBaseStore = defineStore('base', {
|
||||
// await _checkDictWords(this.currentStudyWordDict)
|
||||
let current = this.word.bookList[this.word.studyIndex]
|
||||
let dictResourceUrl = `./dicts/${current.language}/${current.type}/${current.url}`;
|
||||
current.words = await getDictFile(dictResourceUrl)
|
||||
|
||||
let s = await getDictFile(dictResourceUrl)
|
||||
current.words = cloneDeep(s.map(v => {
|
||||
v.id = nanoid(6)
|
||||
return v
|
||||
}))
|
||||
console.log('this.current', current)
|
||||
}
|
||||
if (this.article.studyIndex >= 0) {
|
||||
|
||||
@@ -269,7 +269,6 @@ export const DefaultShortcutKeyMap = {
|
||||
[ShortcutKey.TogglePanel]: 'Ctrl+L',
|
||||
}
|
||||
|
||||
|
||||
export enum TranslateEngine {
|
||||
Baidu = 0,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user