feat:remove unuse components

This commit is contained in:
zyronon
2025-07-21 02:42:31 +08:00
parent a0f30a4b30
commit 0e2fc23161
12 changed files with 151 additions and 250 deletions

View File

@@ -91,7 +91,7 @@ export function useArticleOptions() {
export function syncMyDictList(dict: Dict, isCustom = true) {
const store = useBaseStore()
//任意修改,都将其变为自定义词典
dict.isCustom = isCustom
dict.custom = isCustom
if (isArticle(dict.type)) {
dict.length = dict.articles.length
} else {

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import {Dict} from "@/types.ts";
import DictItem from "./DictItem.vue";
defineProps<{
list?: Dict[],
@@ -17,11 +16,7 @@ const emit = defineEmits<{
<template>
<div class="dict-list">
<DictItem v-for="(dict,index) in list"
:active="selectId === dict.id"
@click="emit('selectDict',{dict,index})"
@add="emit('add')"
:dict="dict"/>
</div>
</template>
@@ -32,4 +27,4 @@ const emit = defineEmits<{
gap: 15rem;
}
</style>
</style>

View File

@@ -47,7 +47,7 @@ async function onSubmit() {
})
let source = [store.article, store.word][props.isBook ? 0 : 1]
//任意修改,都将其变为自定义词典
data.isCustom = true
data.custom = true
if (props.isAdd) {
data.id = 'custom-dict-' + Date.now()

View File

@@ -0,0 +1,33 @@
<script setup lang="ts">
import {Dict} from "@/types.ts";
import {Icon} from "@iconify/vue";
defineProps<{
item?: Dict
quantifier?: string
isAdd: boolean
}>()
</script>
<template>
<div class="book">
<template v-if="!isAdd">
<div>
<div>{{ item?.name }}</div>
<div class="text-sm line-clamp-3" v-opacity="item.name !== item.description">{{ item?.description }}</div>
</div>
<div class="absolute bottom-4 right-4">{{ item?.words?.length }}{{ quantifier }}</div>
</template>
<div v-else class="center h-full">
<Icon
width="40px"
icon="fluent:add-20-filled"/>
</div>
</div>
</template>
<style scoped lang="scss">
</style>

View File

@@ -1,71 +0,0 @@
<script setup lang="ts">
import {DictResource} from "@/types.ts";
import DictItem from "@/pages/pc/components/list/DictItem.vue";
const props = defineProps<{
item: {
list: any[],
tags: string[],
name: string,
},
selectId: string
}>()
const emit = defineEmits<{
selectDict: [val: { dict: DictResource, index: number }]
detail: [],
}>()
let currentTag = $ref(props.item.tags[0])
let localList = $computed(() => {
return props.item.list.filter(v => v.tags.includes(currentTag))
})
</script>
<template>
<div class="dict-group">
<div class="flex items-start border py-4">
<div class="text-xl break-keep mt-1">{{ item.name }}</div>
<div class="tags">
<div class="tag" :class="i === currentTag &&'active'"
@click="currentTag = i"
v-for="i in item.tags">{{ i }}
</div>
</div>
</div>
<div class="dict-list1 grid grid-cols-4 gap-4">
<DictItem v-for="(dict,index) in localList"
:active="selectId === dict.id"
@click="emit('selectDict',{dict,index})"
:dict="dict"/>
</div>
</div>
</template>
<style scoped lang="scss">
.dict-group {
color: var(--color-font-1);
margin-bottom: 1.5rem;
.border {
border-top: 1px dashed gray;
}
}
.tags {
display: flex;
flex-wrap: wrap;
.tag {
color: var(--color-font-1);
cursor: pointer;
padding: 0.4rem 1rem;
border-radius: 2rem;
&.active {
color: var(--color-font-active-1);
background: gray;
}
}
}
</style>

View File

@@ -1,46 +0,0 @@
<script setup lang="ts">
import {DictResource} from "@/types.ts";
import {Icon} from "@iconify/vue";
import BaseIcon from "@/components/BaseIcon.vue";
const props = defineProps<{
dict?: DictResource,
active?: boolean
showDel?: boolean
}>()
const emit = defineEmits<{
add: []
del: []
}>()
</script>
<template>
<div
class="book anim"
:class="active && 'active'"
>
<template v-if="dict.id">
<div class="top">
<div class="name">{{ dict.name }}</div>
<div class="desc" :style="{opacity:dict.name !== dict.description?1:0}">{{ dict.description }}</div>
</div>
<div class="bottom">
<div class="num text-align-right">{{ dict.length + '词' }}</div>
</div>
<div class="del" v-if="dict.showDel && !active">
<BaseIcon icon="solar:trash-bin-minimalistic-linear" @click="emit('del')"/>
</div>
</template>
<div v-else class="add" @click.stop="emit('add')">
<Icon icon="fluent:add-20-filled" width="38" color="#929596"/>
</div>
</div>
</template>
<style scoped lang="scss">
</style>

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import {Dict, DictResource} from "@/types.ts";
import {Icon} from "@iconify/vue";
import DictItem from "@/pages/pc/components/list/DictItem.vue";
import {Dict} from "@/types.ts";
import Book from "@/pages/pc/components/Book.vue";
defineProps<{
list?: DictResource[],
list?: Dict[],
selectId?: string
}>()
@@ -19,12 +18,11 @@ const emit = defineEmits<{
<template>
<div class="grid grid-cols-6 gap-4 ">
<DictItem v-for="(dict,index) in list"
:active="selectId === dict.id"
@click="emit('selectDict',{dict,index})"
@add="emit('add')"
@del="emit('del',{dict,index})"
:dict="dict"/>
<Book v-for="(dict,index) in list"
:is-add="false"
@click="emit('selectDict',{dict,index})"
quantifier="个词"
:item="dict"/>
</div>
</template>

View File

@@ -5,7 +5,7 @@ import {getDefaultWord} from "@/types";
import type {Word} from "@/types";
import BasePage from "@/pages/pc/components/BasePage.vue";
import {computed, onMounted, reactive} from "vue";
import {computed, nextTick, onMounted, reactive} from "vue";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {assign, cloneDeep} from "lodash-es";
import {nanoid} from "nanoid";
@@ -19,6 +19,7 @@ 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";
import {_nextTick} from "@/utils";
const runtimeStore = useRuntimeStore()
const base = useBaseStore()
@@ -42,31 +43,23 @@ onMounted(() => {
}
})
let wordFormData = $ref({
where: '',
type: '',
id: '',
index: 0
})
enum FormMode {
None = '',
Add = 'Add',
Edit = 'Edit',
const getDefaultFormWord = () => {
return {
id: '',
word: '',
phonetic0: '',
phonetic1: '',
trans: '',
sentences: '',
phrases: '',
synos: '',
relWords: '',
etymology: '',
}
}
const DefaultFormWord = {
word: '',
phonetic0: '',
phonetic1: '',
trans: '',
sentences: '',
phrases: '',
synos: '',
relWords: '',
etymology: '',
}
let wordForm = $ref(cloneDeep(DefaultFormWord))
let isOperate = $ref(false)
let wordForm = $ref(getDefaultFormWord())
let wordFormRef = $ref<FormInstance>()
const wordRules = reactive<FormRules>({
word: [
@@ -170,6 +163,7 @@ function convertToWord(raw) {
});
return getDefaultWord({
id: raw.id,
word: safeString(raw.word),
phonetic0: safeString(raw.phonetic0),
phonetic1: safeString(raw.phonetic1),
@@ -183,52 +177,69 @@ function convertToWord(raw) {
});
}
function syncDictInMyStudyList(study = false) {
_nextTick(() => {
let rIndex = base.word.bookList.findIndex(v => v.id === runtimeStore.editDict.id)
let temp = cloneDeep(runtimeStore.editDict);
temp.custom = true
if (rIndex > -1) {
base.word.bookList[base.word.studyIndex] = temp
if (study) base.word.studyIndex = rIndex
} else {
base.word.bookList.push(temp)
if (study) base.word.studyIndex = base.word.bookList.length - 1
}
}, 100)
}
//TODO trans结构变了
async function onSubmitWord() {
await wordFormRef.validate((valid, fields) => {
await wordFormRef.validate((valid) => {
if (valid) {
let data: any = convertToWord(wordForm)
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)
ElMessage.success('添加成功')
wordForm = cloneDeep(DefaultFormWord)
// setTimeout(wordListRef?.scrollToBottom, 100)
} else {
let r = list.find(v => v.id === wordFormData.id)
if (data.id) {
let r = list.find(v => v.id === data.id)
if (r) {
assign(r, data)
ElMessage.success('修改成功')
}else {
} else {
ElMessage.success('修改失败,未找到单词')
return
}
} else {
data.id = nanoid(6)
data.checked = false
let r = list.find(v => v.word === wordForm.word)
if (r) {
ElMessage.warning('已有相同名称单词!')
return
} else list.push(data)
ElMessage.success('添加成功')
wordForm = getDefaultFormWord()
}
syncDictInMyStudyList()
} else {
ElMessage.warning('请填写完整')
}
})
}
function delWord(id: string) {
function delWord(id: string, isBatch = false) {
let rIndex2 = list.findIndex(v => v.id === id)
if (rIndex2 > -1) {
list.splice(rIndex2, 1)
}
// if (wordFormData.type === FormMode.Edit && wordForm.word === val.item.word) {
// closeWordForm()
// }
if (!isBatch) syncDictInMyStudyList()
}
function batchDel(ids: string[]) {
ids.map(v => delWord(v))
ids.map(v => delWord(v, true))
syncDictInMyStudyList()
}
function editWord(word: Word) {
wordFormData.type = FormMode.Edit
wordFormData.id = word.id
isOperate = true
wordForm.id = word.id
wordForm.word = word.word
wordForm.phonetic1 = word.phonetic1
wordForm.phonetic0 = word.phonetic0
@@ -243,13 +254,13 @@ function editWord(word: Word) {
function addWord() {
// setTimeout(wordListRef?.scrollToBottom, 100)
wordFormData.type = FormMode.Add
wordForm = cloneDeep(DefaultFormWord)
isOperate = true
wordForm = getDefaultFormWord()
}
function closeWordForm() {
wordFormData.type = FormMode.None
wordForm = cloneDeep(DefaultFormWord)
isOperate = false
wordForm = getDefaultFormWord()
}
let isEdit = $ref(false)
@@ -339,10 +350,10 @@ defineRender(() => {
</BaseTable>
</div>
{
wordFormData.type ? (
isOperate ? (
<div class="flex-1 flex flex-col ml-4">
<div class="common-title">
{wordFormData.type === FormMode.Add ? '添加' : '修改'}单词
{wordForm.id ? '修改' : '添加'}单词
</div>
<el-form
class="flex-1 overflow-auto pr-2"

View File

@@ -8,16 +8,14 @@ import BaseIcon from "@/components/BaseIcon.vue";
import Dialog from "@/pages/pc/components/dialog/Dialog.vue";
import {_getAccomplishDate, _getAccomplishDays, _getDictDataByUrl, useNav} from "@/utils";
import BasePage from "@/pages/pc/components/BasePage.vue";
import {Dict, DictResource, getDefaultDict} from "@/types.ts";
import {Dict, DictResource} from "@/types.ts";
import {onMounted} from "vue";
import {getCurrentStudyWord} from "@/hooks/dict.ts";
import {usePracticeStore} from "@/stores/practice.ts";
import {EventKey, useEvent} from "@/utils/eventBus.ts";
import DictListPanel from "@/pages/pc/components/DictListPanel.vue";
import DictGroup from "@/pages/pc/components/list/DictGroup.vue";
import {cloneDeep} from "lodash-es";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {getArticleBookDataByUrl} from "@/utils/article.ts";
import Book from "@/pages/pc/components/Book.vue";
const store = useBaseStore()
const router = useRouter()
@@ -157,20 +155,13 @@ function addDict() {
<div class="color-blue cursor-pointer" @click="addDict">创建个人词典</div>
</div>
<div class="grid grid-cols-6 gap-4 mt-4">
<div class="book" v-for="item in store.word.bookList" @click="goDictDetail2(item)">
<div>
<div>{{ item.name }}</div>
<div>{{ item.description }}</div>
</div>
<div class="absolute bottom-4 right-4">{{ item.words.length }}个词</div>
</div>
<div class="book" @click="dictListRef.startSearch()">
<div class="center h-full">
<Icon
width="40px"
icon="fluent:add-20-filled"/>
</div>
</div>
<Book :is-add="false"
quantifier="个词"
:item="item"
v-for="item in store.word.bookList"
@click="goDictDetail2(item)"/>
<Book :is-add="true"
@click="dictListRef.startSearch()"/>
</div>
</div>

View File

@@ -175,8 +175,10 @@ export const useBaseStore = defineStore('base', {
if (this.word.studyIndex >= 3) {
// await _checkDictWords(this.currentStudyWordDict)
let current = this.word.bookList[this.word.studyIndex]
this.word.bookList[this.word.studyIndex] = await _getDictDataByUrl(current)
let current: Dict = this.word.bookList[this.word.studyIndex]
if (!current.custom) {
this.word.bookList[this.word.studyIndex] = await _getDictDataByUrl(current)
}
console.log('this.current', current)
}
if (this.article.studyIndex >= 1) {
@@ -236,7 +238,7 @@ export const useBaseStore = defineStore('base', {
}
} else {
//如果不是自定义词典并且有url地址才去下载
if (!dict.isCustom && dict.url) {
if (!dict.custom && dict.url) {
if (!dict.originWords.length) {
let v = await getDictFile(url)
v.map(s => {

View File

@@ -68,18 +68,6 @@ export const PronunciationApi = 'https://dict.youdao.com/dictvoice?audio='
export type TranslateLanguageType = 'en' | 'zh-CN' | 'ja' | 'de' | 'common' | ''
export type LanguageType = 'en' | 'ja' | 'de' | 'code'
export type DictResource = {
id: string
name: string
description: string
url: string
length: number
category: string
tags: string[]
translateLanguage: TranslateLanguageType
type: DictType
language: LanguageType
}
export enum DictType {
collect = 'collect',
@@ -237,51 +225,48 @@ export const languageCategoryOptions = [
{id: 'my', name: '我的', flag: myFlag},
]
export type DictResource = {
id: string
name: string
description: string
url: string
length: number
category: string
tags: string[]
translateLanguage: TranslateLanguageType
type: DictType
language: LanguageType
}
export function getDefaultDict(val: Partial<Dict> = {}): Dict {
return {
id: '',
name: '',
description: '',
url: '',
length: 0,
category: '',
tags: [],
translateLanguage: '',
type: DictType.word,
language: 'en',
lastLearnIndex: 0,
perDayStudyNumber: 20,
description: '',
words: [],
articles: [],
statistics: [],
isCustom: false,
length: 0,
/*资源属性*/
resourceId: '',
fileName: '',
category: '',
tags: [],
dictType: DictType.word,
langTypeStr: 'en',
tranTypeStr: 'zh',
version: 0,
custom: false,
...val
}
}
export interface Dict {
id: any,
name: string,
export interface Dict extends DictResource {
lastLearnIndex: number,
perDayStudyNumber: number,
description: string,
words: Word[],
articles: Article[],
statistics: Statistics[],
isCustom: boolean,
length: number,
/*资源属性*/
resourceId: string,
category: string
tags: string[]
dictType: DictType
fileName: string,
langTypeStr: string,
tranTypeStr: string,
version: number,
custom: boolean,
}
export interface ArticleItem {

View File

@@ -117,8 +117,11 @@ export function checkAndUpgradeSaveSetting(val: any) {
//筛选未自定义的词典,未自定义的词典不需要保存单词,用的时候再下载
export function shakeCommonDict(n: BaseState): BaseState {
let data: BaseState = cloneDeep(n)
data.wordDictList.map((v: Dict) => {
if (!v.isCustom) v.words = []
data.word.bookList.map((v: Dict) => {
if (!v.custom) v.words = []
})
data.article.bookList.map((v: Dict) => {
if (!v.custom) v.words = []
})
return data
}
@@ -180,7 +183,7 @@ export async function _checkDictWords(dict: Dict) {
} else {
//TODO 需要和其他需要下载的地方统一
//如果不是自定义词典并且有url地址才去下载
if (!dict.isCustom && dict.fileName) {
if (!dict.custom && dict.fileName) {
// let rrr = await axios('http://localhost/static/dict/en/zh/Top50Prepositions-v1.json')
// console.log('r', rrr)
// return
@@ -285,7 +288,7 @@ export function _parseLRC(lrc: string): { start: number, end: number, text: stri
return parsed;
}
export async function _getDictDataByUrl(val: DictResource) {
export async function _getDictDataByUrl(val: Dict) {
let dictResourceUrl = `./dicts/${val.language}/word/${val.url}`.replace('.json', '_v2.json');
let s = await getDictFile(dictResourceUrl)
let words = cloneDeep(s.map(v => {