save
This commit is contained in:
@@ -17,11 +17,17 @@ const props = withDefaults(defineProps<{
|
||||
activeId?: string,
|
||||
isActive?: boolean
|
||||
showBorder?: boolean
|
||||
del?: Function
|
||||
batchDel?: Function
|
||||
add?: Function
|
||||
}>(), {
|
||||
activeIndex: -1,
|
||||
activeId: '',
|
||||
isActive: false,
|
||||
showBorder: false,
|
||||
del: () => void 0,
|
||||
add: () => void 0,
|
||||
batchDel: () => void 0
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -105,8 +111,13 @@ function sort(type: Sort) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleBatchDel() {
|
||||
props.batchDel(selectIds)
|
||||
selectIds = []
|
||||
}
|
||||
|
||||
const s = useSlots()
|
||||
console.log('s', s)
|
||||
|
||||
defineRender(
|
||||
() => {
|
||||
const d = (item) => <el-checkbox
|
||||
@@ -138,13 +149,13 @@ defineRender(
|
||||
<div class="flex gap-2 relative">
|
||||
{
|
||||
selectIds.length ? <BaseIcon
|
||||
onClick={emit('del')}
|
||||
onClick={handleBatchDel}
|
||||
class="del"
|
||||
title="删除"
|
||||
icon="solar:trash-bin-minimalistic-linear"/> : null
|
||||
}
|
||||
<BaseIcon
|
||||
onClick={emit('add')}
|
||||
onClick={props.add}
|
||||
icon="fluent:add-20-filled"
|
||||
title="添加单词"/>
|
||||
<BaseIcon
|
||||
@@ -183,26 +194,7 @@ defineRender(
|
||||
<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>
|
||||
{s.default({checkbox: d, item})}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
151
src/pages/pc/components/WordItem.vue
Normal file
151
src/pages/pc/components/WordItem.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {Word} from "@/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
item: Word,
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
}>(), {
|
||||
showTranslate: true,
|
||||
showWord: true
|
||||
})
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="word-item"
|
||||
:class="{
|
||||
border:true
|
||||
}"
|
||||
>
|
||||
<div class="left">
|
||||
<slot name="prefix" :item="item"></slot>
|
||||
<div class="title-wrapper">
|
||||
<div class="item-title">
|
||||
<span class="word" :class="!showWord && 'word-shadow'">{{ item.word }}</span>
|
||||
<span class="phonetic">{{ item.phonetic0 }}</span>
|
||||
<VolumeIcon class="volume" @click="playWordAudio(item.word)"></VolumeIcon>
|
||||
</div>
|
||||
<div class="item-sub-title" v-if="item.trans.length && showTranslate">
|
||||
<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"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.word-item {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background: var(--color-item-bg);
|
||||
color: var(--color-font-1);
|
||||
font-size: 1.1rem;
|
||||
border-radius: .5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
transition: all .3s;
|
||||
padding: .6rem;
|
||||
gap: .6rem;
|
||||
border: 1px solid var(--color-item-border);
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
gap: .6rem;
|
||||
|
||||
.title-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .2rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .3rem;
|
||||
transition: all .3s;
|
||||
}
|
||||
|
||||
.volume, .collect, .easy {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-item-hover);
|
||||
|
||||
.volume, .collect, .easy {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--color-item-active);
|
||||
$c: #E6A23C;
|
||||
|
||||
.phonetic, .item-sub-title {
|
||||
color: var(--color-gray) !important;
|
||||
}
|
||||
|
||||
.volume, .collect, .easy, .fill {
|
||||
color: $c;
|
||||
}
|
||||
}
|
||||
|
||||
&.border {
|
||||
&.active {
|
||||
.item-title {
|
||||
border-bottom: 2px solid gray !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item-title {
|
||||
transition: all .3s;
|
||||
cursor: pointer;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.item-title {
|
||||
border-bottom: 2px solid gray !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
color: var(--color-font-1);
|
||||
|
||||
.word {
|
||||
font-size: 1.2rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.phonetic {
|
||||
font-size: .9rem;
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
|
||||
.item-sub-title {
|
||||
font-size: 1rem;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
|
||||
import {Word} from "@/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import BaseList from "@/pages/pc/components/list/BaseList.vue";
|
||||
|
||||
@@ -10,6 +10,9 @@ import {nanoid} from "nanoid";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {_checkDictWords, 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";
|
||||
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const store = useBaseStore()
|
||||
@@ -31,7 +34,7 @@ onMounted(() => {
|
||||
runtimeStore.editDict = cloneDeep(runtimeStore.routeData)
|
||||
_checkDictWords(runtimeStore.editDict)
|
||||
}
|
||||
// break
|
||||
break
|
||||
case 0:
|
||||
runtimeStore.editDict = cloneDeep(store.collectWord)
|
||||
break
|
||||
@@ -111,21 +114,18 @@ async function onSubmitWord() {
|
||||
})
|
||||
}
|
||||
|
||||
function delWord(val: {
|
||||
item: Word
|
||||
}) {
|
||||
let rIndex2 = list.findIndex(v => v.id === val.item.id)
|
||||
function delWord(id: string) {
|
||||
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 (wordFormData.type === FormMode.Edit && wordForm.word === val.item.word) {
|
||||
// closeWordForm()
|
||||
// }
|
||||
}
|
||||
|
||||
function batchDelWord() {
|
||||
console.log('multipleSelection', multipleSelection)
|
||||
multipleSelection.map(v => delWord({item: v}))
|
||||
function batchDel(ids: string[]) {
|
||||
ids.map(v => delWord(v))
|
||||
}
|
||||
|
||||
function editWord(word: Word,) {
|
||||
@@ -149,16 +149,10 @@ function closeWordForm() {
|
||||
}
|
||||
|
||||
defineRender(() => {
|
||||
let d = (i) => {
|
||||
console.log('i', i)
|
||||
return <div>
|
||||
{i.checkbox(i.item)}
|
||||
</div>
|
||||
}
|
||||
return (
|
||||
<BasePage>
|
||||
<header class="flex gap-4 mb-2 items-center">
|
||||
<BaseIcon onClick={back} icon="octicon:arrow-left-24" width="20"/>
|
||||
<BaseIcon onClick={back} icon="octicon:arrow-left-24" width={20}/>
|
||||
<div class="left">
|
||||
<div class="top">
|
||||
<div class="text-xl">
|
||||
@@ -176,8 +170,32 @@ defineRender(() => {
|
||||
<BaseTable
|
||||
class="h-full"
|
||||
list={list}
|
||||
del={delWord}
|
||||
batchDel={batchDel}
|
||||
add={addWord}
|
||||
>
|
||||
{d}
|
||||
{
|
||||
(val) =>
|
||||
<WordItem item={val.item}>
|
||||
{{
|
||||
prefix: () => val.checkbox(val.item),
|
||||
suffix: () => (
|
||||
<div class='flex flex-col'>
|
||||
<BaseIcon
|
||||
class="del"
|
||||
onClick={() => editWord(val.item)}
|
||||
title="编辑"
|
||||
icon="tabler:edit"/>
|
||||
<BaseIcon
|
||||
class="del"
|
||||
onClick={() => delWord(val.item.id)}
|
||||
title="删除"
|
||||
icon="solar:trash-bin-minimalistic-linear"/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</WordItem>
|
||||
}
|
||||
</BaseTable>
|
||||
</div>
|
||||
{
|
||||
|
||||
@@ -65,6 +65,7 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
},
|
||||
|
||||
{
|
||||
"id": "calculate",
|
||||
"word": "calculate",
|
||||
"trans": [
|
||||
{
|
||||
@@ -78,6 +79,7 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
"phonetic1": "ˈkælkjəˌlet"
|
||||
},
|
||||
{
|
||||
"id": "compete",
|
||||
"word": "compete",
|
||||
"trans": [
|
||||
{
|
||||
@@ -88,6 +90,7 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
"phonetic1": "kəmˈpit"
|
||||
},
|
||||
{
|
||||
"id": "furnish",
|
||||
"word": "furnish",
|
||||
"trans": [
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@ import jaFlag from "@/assets/img/flags/ja.png";
|
||||
import deFlag from "@/assets/img/flags/de.png";
|
||||
import codeFlag from "@/assets/img/flags/code.png";
|
||||
import myFlag from "@/assets/img/flags/my.png";
|
||||
import {DefaultChapterWordNumber} from "@/stores/setting.ts";
|
||||
|
||||
export type WordTrans = {
|
||||
pos: string,
|
||||
|
||||
Reference in New Issue
Block a user