remove surplus list

This commit is contained in:
zyronon
2023-12-01 23:49:11 +08:00
parent bdd3b501a0
commit be4912cb40
23 changed files with 99 additions and 999 deletions

View File

@@ -7,7 +7,6 @@ import {Icon} from "@iconify/vue";
defineProps<{
title?: string,
icon: string,
className?: string
}>()
defineEmits(['click'])
@@ -15,7 +14,7 @@ defineEmits(['click'])
<template>
<Tooltip :title="title">
<IconWrapper :class="className">
<IconWrapper v-bind="$attrs">
<Icon @click.stop="$emit('click')" :icon="icon"/>
</IconWrapper>
</Tooltip>

View File

@@ -52,28 +52,40 @@ async function selectDict(val: { dict: DictResource | Dict, index: number }) {
...cloneDeep(DefaultDict),
...item,
})
runtimeStore.editDict.id = nanoid(6)
//设置默认章节单词数
runtimeStore.editDict.chapterWordNumber = settingStore.chapterWordNumber
}
if ([DictType.collect, DictType.simple, DictType.wrong].includes(runtimeStore.editDict.type)) {
} else {
let url = `./dicts/${runtimeStore.editDict.language}/${runtimeStore.editDict.type}/${runtimeStore.editDict.translateLanguage}/${runtimeStore.editDict.url}`;
if (runtimeStore.editDict.type === DictType.word) {
if (!runtimeStore.editDict.originWords.length) {
let r = await fetch(url)
let v = await r.json()
runtimeStore.editDict.originWords = cloneDeep(v)
changeSort(runtimeStore.editDict.sort)
//如果不是自定义词典并且有url地址才去下载
if (!runtimeStore.editDict.isCustom && runtimeStore.editDict.url) {
let url = `./dicts/${runtimeStore.editDict.language}/${runtimeStore.editDict.type}/${runtimeStore.editDict.translateLanguage}/${runtimeStore.editDict.url}`;
if (runtimeStore.editDict.type === DictType.word) {
if (!runtimeStore.editDict.originWords.length) {
let r = await fetch(url)
let v = await r.json()
v.map(s => {
s.id = nanoid(6)
})
runtimeStore.editDict.originWords = cloneDeep(v)
changeSort(runtimeStore.editDict.sort)
} else {
runtimeStore.editDict.length = runtimeStore.editDict.words.length + runtimeStore.editDict.residueWords.length
}
}
}
if (runtimeStore.editDict.type === DictType.article) {
if (!runtimeStore.editDict.articles.length) {
let r = await fetch(url)
let v = await r.json()
runtimeStore.editDict.articles = cloneDeep(v.map(s => {
s.id = nanoid(6)
return s
}))
if (runtimeStore.editDict.type === DictType.article) {
if (!runtimeStore.editDict.articles.length) {
let r = await fetch(url)
let v = await r.json()
v.map(s => {
s.id = nanoid(6)
})
runtimeStore.editDict.articles = cloneDeep(v)
} else {
runtimeStore.editDict.length = runtimeStore.editDict.articles.length
}
}
}
}
@@ -121,24 +133,13 @@ function changeSort(v) {
resetChapterList()
}
function editDict() {
show = false
setTimeout(() => {
router.push({path: '/dict', query: {type: 'editDict'}})
}, 500)
}
let wordListRef: any = $ref()
function add() {
function option(type: string) {
show = false
setTimeout(() => {
router.push({path: '/dict', query: {type: 'addWordOrArticle'}})
router.push({path: '/dict', query: {type: type}})
}, 500)
if (dictIsArticle) {
} else {
}
}
/**/
@@ -215,9 +216,10 @@ function showWordListModal(val: { item: Word, index: number }) {
<div class="left-column">
<BaseIcon
v-if="![DictType.collect,DictType.wrong,DictType.simple].includes(runtimeStore.editDict.type)"
class-name="edit-icon"
class="edit-icon"
title="编辑词典"
icon="tabler:edit"
@click='editDict'
@click='option("editDict")'
/>
<div class="name">{{ runtimeStore.editDict.name }}</div>
<div class="desc">{{ runtimeStore.editDict.description }}</div>
@@ -230,7 +232,8 @@ function showWordListModal(val: { item: Word, index: number }) {
}}</span>
</div>
<BaseIcon icon="mi:add"
@click='add'
@click='option("addWordOrArticle")'
:title="`添加${dictIsArticle?'文章':'单词'}`"
/>
</div>
<div class="text">开始日期-</div>
@@ -322,7 +325,15 @@ function showWordListModal(val: { item: Word, index: number }) {
</div>
</div>
<div class="right-column">
<div class="common-title">{{ dictIsArticle ? '文章' : '章节' }}列表</div>
<div class="common-title">
<span>{{ dictIsArticle ? '文章' : '章节' }}列表</span>
<BaseIcon
icon="fluent:notepad-edit-20-regular"
@click='option("detail")'
style="position: absolute;right: 20rem;"
:title="`管理${dictIsArticle?'文章':'章节'}`"
/>
</div>
<template v-if="dictIsArticle">
<ArticleList4
v-if="runtimeStore.editDict.articles.length"
@@ -457,13 +468,13 @@ $header-height: 60rem;
padding-right: var(--space);
.name {
font-size: 28rem;
margin-bottom: 10rem;
font-size: 24rem;
width: 95%;
}
.desc {
font-size: 18rem;
margin-bottom: 30rem;
font-size: 16rem;
margin-bottom: 20rem;
}
.count {
@@ -471,13 +482,9 @@ $header-height: 60rem;
border-bottom: 2px solid var(--color-item-active);
}
.edit-icon {
}
:deep(.edit-icon) {
position: absolute;
top: 8rem;
top: 0;
right: 0;
}
}

View File

@@ -5,7 +5,7 @@ import {$ref} from "vue/macros";
import {onMounted, onUnmounted, watch} from "vue";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
import VirtualWordList from "@/components/list/VirtualWordList.vue";
import WordList from "@/components/list2/WordList.vue";
let show = $ref(false)
let loading = $ref(false)
@@ -18,7 +18,7 @@ onMounted(() => {
emitter.on(EventKey.openWordListModal, (val: any) => {
show = true
list = val.list
title = val.title
title = val.title + `(${list.length}词)`
requestIdleCallback(() => {
let count = 0
if (val.translateLanguage === 'common') {
@@ -77,10 +77,10 @@ onUnmounted(() => {
:indeterminate="false"
:show-text="false"/>
</div>
<VirtualWordList
<WordList
class="word-list"
:list="list">
</VirtualWordList>
</WordList>
</div>
</Dialog>
</template>
@@ -93,6 +93,8 @@ onUnmounted(() => {
padding-top: 0;
width: 400rem;
height: 75vh;
display: flex;
flex-direction: column;
.progress-wrapper {
padding: 0 var(--space);

View File

@@ -1,122 +0,0 @@
<script setup lang="ts">
import Input from "@/components/Input.vue";
import {$computed, $ref} from "vue/macros";
import {Article, Word} from "@/types.ts";
import ListItem from "@/components/list/ListItem.vue";
import {useSettingStore} from "@/stores/setting.ts";
import {watch} from "vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
const props = withDefaults(defineProps<{
list: Article[],
activeIndex?: number,
isActive?: boolean
showTranslate?: boolean
}>(), {
activeIndex: -1,
isActive: false
})
const emit = defineEmits<{
selectItem: [val: Article],
delSelectItem: [],
'update:searchKey': [val: string],
'update:list': [list: Article[]],
}>()
let searchKey = $ref('')
let localList = $computed({
get() {
if (searchKey) {
return props.list.filter((item: Article) => {
//把搜索内容,分词之后,判断是否有这个词,比单纯遍历包含体验更好
return searchKey.toLowerCase().split(' ').filter(v => v).some(value => {
return item.title.toLowerCase().includes(value) || item.titleTranslate.toLowerCase().includes(value)
})
})
} else {
return props.list
}
},
set(newValue) {
emit('update:list', newValue)
}
})
const settingStore = useSettingStore()
const listRef: HTMLElement = $ref(null as any)
function scrollViewToCenter(index: number) {
if (index === -1) return
listRef.children[index + 1]?.scrollIntoView({block: 'center', behavior: 'smooth'})
}
watch(() => props.activeIndex, (n: any) => {
if (settingStore.showPanel) {
scrollViewToCenter(n)
}
})
watch(() => props.isActive, (n: boolean) => {
setTimeout(() => {
if (n) scrollViewToCenter(props.activeIndex)
}, 300)
})
watch(() => props.list, () => {
listRef.scrollTo(0, 0)
})
</script>
<template>
<div class="list" ref="listRef">
<div class="search">
<Input v-model="searchKey"/>
</div>
<div class="common-list-item"
v-for="(source,index) in localList" :key="index"
:class="{active:activeIndex === index}"
@click="emit('selectItem',source)"
>
<div class="left">
<div class="title-wrapper">
<div class="item-title">
<div class="name"> {{ `${index + 1}. ${source.title}` }}</div>
</div>
<div class="item-sub-title" v-if="source.titleTranslate && showTranslate">
<div class="item-translate"> {{ ` ${source.titleTranslate}` }}</div>
</div>
</div>
</div>
<div class="right">
<slot :source="source" :index="index"></slot>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/variable.scss";
.list {
display: flex;
flex-direction: column;
gap: 15rem;
flex: 1;
overflow: overlay;
padding: 0 var(--space);
.search {
box-sizing: border-box;
width: 100%;
}
.translate {
font-size: 16rem;
}
}
</style>

View File

@@ -1,158 +0,0 @@
<script setup lang="ts">
import Input from "@/components/Input.vue";
import {$computed, $ref} from "vue/macros";
import {Article, Word} from "@/types.ts";
import ListItem from "@/components/list/ListItem.vue";
import {useSettingStore} from "@/stores/setting.ts";
import {watch} from "vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
const props = withDefaults(defineProps<{
list: Article[],
activeIndex?: number,
isActive?: boolean
showTranslate?: boolean
}>(), {
list: [],
activeIndex: -1,
isActive: false,
showTranslate:true
})
const emit = defineEmits<{
click: [val: { data: Article, index: number }],
delSelectItem: [],
'update:searchKey': [val: string],
'update:list': [list: Article[]],
}>()
let searchKey = $ref('')
let localList = $computed({
get() {
if (searchKey) {
return props.list.filter((item: Article) => {
//把搜索内容,分词之后,判断是否有这个词,比单纯遍历包含体验更好
return searchKey.toLowerCase().split(' ').filter(v => v).some(value => {
return item.title.toLowerCase().includes(value) || item.titleTranslate.toLowerCase().includes(value)
})
})
} else {
return props.list
}
},
set(newValue) {
emit('update:list', newValue)
}
})
const settingStore = useSettingStore()
const listRef: HTMLElement = $ref(null as any)
// function scrollViewToCenter(index: number) {
// if (index === -1) return
// listRef.children[index + 1]?.scrollIntoView({block: 'center', behavior: 'smooth'})
// }
//
// watch(() => props.activeIndex, (n: any) => {
// if (settingStore.showPanel) {
// scrollViewToCenter(n)
// }
// })
//
// watch(() => props.isActive, (n: boolean) => {
// setTimeout(() => {
// if (n) scrollViewToCenter(props.activeIndex)
// }, 300)
// })
watch(() => props.list, () => {
// listRef.scrollTo(0, 0)
})
function scrollToBottom() {
listRef.scrollToBottom()
}
function scrollToItem(index: number) {
listRef.scrollToItem(index)
}
defineExpose({scrollToBottom, scrollToItem})
</script>
<template>
<div class="list">
<div class="search">
<Input v-model="searchKey"/>
</div>
<DynamicScroller
:items="list"
ref="listRef"
:min-item-size="90"
class="scroller"
>
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[
item.id,
]"
:data-index="index"
>
<div class="list-item-wrapper">
<div class="common-list-item"
:class="{active:activeIndex === index}"
@click="emit('click',{data:item,index})"
>
<div class="left">
<slot name="prefix" :data="item" :index="index"></slot>
<div class="title-wrapper">
<div class="item-title">
<div class="name"> {{ `${index + 1}. ${item.title}` }}</div>
</div>
<div class="item-sub-title" v-if="item.titleTranslate && showTranslate">
<div class="item-translate"> {{ ` ${item.titleTranslate}` }}</div>
</div>
</div>
</div>
<div class="right">
<slot :data="item" :index="index"></slot>
</div>
</div>
</div>
</DynamicScrollerItem>
</template>
</DynamicScroller>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/variable.scss";
.list {
display: flex;
flex-direction: column;
gap: 15rem;
flex: 1;
height: 100%;
.search {
box-sizing: border-box;
width: 100%;
padding: 0 var(--space);
}
.translate {
font-size: 16rem;
}
.scroller {
flex: 1;
padding: 0 var(--space);
}
}
</style>

View File

@@ -1,108 +0,0 @@
<script setup lang="ts">
import {Dict, Word} from "@/types.ts"
import {emitter, EventKey} from "@/utils/eventBus.ts";
import {$computed} from "vue/macros";
import {useRuntimeStore} from "@/stores/runtime.ts";
import BaseIcon from "@/components/BaseIcon.vue";
const props = defineProps<{
dict: Dict,
activeIndex?: number
isArticle?: boolean
}>()
const emit = defineEmits<{
'update:activeIndex': [index: number]
}>()
const runtimeStore = useRuntimeStore()
const list: any[] = $computed(() => {
if (props.isArticle) return props.dict.articles
return props.dict.chapterWords
})
function showWordListModal(index: number, item: Word[]) {
emitter.emit(EventKey.openWordListModal, {
title: `${index + 1}`,
translateLanguage: runtimeStore.editDict.translateLanguage,
list: item
})
}
</script>
<template>
<div class="list">
<div class="common-list-item"
:class="activeIndex === index && 'active'"
v-for="(item,index) in list"
@click="emit('update:activeIndex', index)">
<div class="flex gap10">
<input type="radio" :checked="activeIndex === index">
<div class="left">
<div class="title-wrapper">
<template v-if="isArticle">
<div class="item-title"
@click.stop="emitter.emit(EventKey.openArticleListModal,item)"
>{{ index + 1 }}.&nbsp;{{ item.title }}
</div>
<div class="item-sub-title" v-if="item.titleTranslate"> {{ item.titleTranslate }}</div>
</template>
<template v-else>
<div class="item-title"
@click.stop="showWordListModal(index,item)"
>{{ index + 1 }}&nbsp;&nbsp;&nbsp;{{ item.length }}
</div>
</template>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/variable";
.list {
display: flex;
flex-direction: column;
width: 100%;
flex: 1;
overflow: auto;
box-sizing: border-box;
gap: 10rem;
padding: 0 var(--space);
//padding-right: 10rem;
.common-list-item {
input {
cursor: pointer;
}
.item-title {
transition: all .3s;
cursor: pointer;
border-bottom: 2px solid transparent;
}
:deep(.del) {
opacity: 0;
}
&:hover {
.item-title {
border-bottom: 2px solid gray !important;
}
:deep(.del) {
opacity: 1;
}
}
}
}
</style>

View File

@@ -1,91 +0,0 @@
<script setup lang="ts">
import {Word} from "../../types.ts";
import {useSettingStore} from "@/stores/setting.ts";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {usePlayWordAudio} from "@/hooks/sound.ts";
import {watch} from 'vue'
const props = withDefaults(defineProps<{
list: Word[],
activeIndex?: number,
isActive?: boolean
showTranslate?: boolean
showWord?: boolean
}>(), {
activeIndex: -1,
isActive: false,
showTranslate: true,
showWord: true
})
const emit = defineEmits<{
change: [val: { word: Word, index: number }],
}>()
const settingStore = useSettingStore()
const listRef: HTMLElement = $ref(null as any)
function scrollViewToCenter(index: number) {
if (index === -1) return
listRef.children[index]?.scrollIntoView({block: 'center', behavior: 'smooth'})
}
watch(() => props.activeIndex, (n: any) => {
if (settingStore.showPanel) {
scrollViewToCenter(n)
}
})
watch(() => props.isActive, (n: boolean) => {
setTimeout(() => {
if (n) scrollViewToCenter(props.activeIndex)
}, 300)
})
watch(() => props.list, () => {
listRef.scrollTo(0, 0)
})
const playWordAudio = usePlayWordAudio()
</script>
<template>
<div class="common-list" ref="listRef">
<div class="common-list-item"
v-for="(source,index) in list" :key="index"
:class="{active:activeIndex === index}"
@click="emit('change',{word:source,index})"
>
<div class="left">
<div class="title-wrapper">
<div class="item-title">
<span class="word" :class="!showWord && 'text-shadow'">{{ source.name }}</span>
<span class="phonetic">{{ source.usphone }}</span>
<VolumeIcon class="volume" @click="playWordAudio(source.name)"></VolumeIcon>
</div>
<div class="item-sub-title" v-if="source.trans.length && showTranslate">
<div v-for="item in source.trans">{{ item }}</div>
</div>
</div>
</div>
<div class="right">
<slot :word="source" :index="index"></slot>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
@import "@/assets/css/variable";
.common-list {
display: flex;
flex-direction: column;
gap: 15rem;
flex: 1;
overflow: overlay;
padding: 0 var(--space);
}
</style>

View File

@@ -1,126 +0,0 @@
<script setup lang="ts">
import BaseIcon from "@/components/BaseIcon.vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
defineProps<{
showVolume?: boolean,
showDel?: boolean,
active?: boolean
isCollect?: boolean
isSimple?: boolean
}>()
defineEmits<{
toggleSimple: [],
toggleCollect: [],
del: [],
}>()
</script>
<template>
<div class="list-item"
:class="{active}"
>
<div class="left">
<slot></slot>
</div>
<div class="right">
<BaseIcon
v-if="showDel"
class-name="del"
@click="$emit('del')"
title="移除"
icon="solar:trash-bin-minimalistic-linear"/>
<template v-else>
<BaseIcon
v-if="!isCollect"
class-name="collect"
@click="$emit('toggleCollect')"
title="收藏" icon="ph:star"/>
<BaseIcon
v-else
class-name="fill"
@click="$emit('toggleCollect')"
title="取消收藏" icon="ph:star-fill"/>
<BaseIcon
v-if="!isSimple"
class-name="easy"
@click="$emit('toggleSimple')"
title="标记为简单词"
icon="material-symbols:check-circle-outline-rounded"/>
<BaseIcon
v-else
class-name="fill"
@click="$emit('toggleSimple')"
title="取消标记简单词"
icon="material-symbols:check-circle-rounded"/>
</template>
</div>
</div>
</template>
<style scoped lang="scss">
.list-item {
.left {
display: flex;
gap: 10rem;
flex-direction: column;
word-break: break-word;
}
.right {
display: flex;
flex-direction: column;
gap: 5rem;
transition: all .3s;
}
:deep(.collect) {
opacity: 0;
}
:deep(.easy) {
opacity: 0;
}
&:hover {
:deep(.collect) {
opacity: 1;
}
:deep(.easy) {
opacity: 1;
}
}
&.active {
:deep(.sub-title) {
//color: black;
}
:deep(.title) {
//color: black;
}
$c: #E6A23C;
:deep(.collect) {
color: $c;
}
:deep(.fill) {
color: $c;
}
:deep(.easy) {
color: $c;
}
}
}
</style>

View File

@@ -1,108 +0,0 @@
<script setup lang="ts">
import {Word} from "../../types.ts";
import {useSettingStore} from "@/stores/setting.ts";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {usePlayWordAudio} from "@/hooks/sound.ts";
import {watch} from 'vue'
const props = withDefaults(defineProps<{
list: Word[],
activeIndex?: number,
isActive?: boolean
showTranslate?: boolean
showWord?: boolean
}>(), {
activeIndex: -1,
isActive: false,
showTranslate: true,
showWord: true
})
const emit = defineEmits<{
change: [val: { word: Word, index: number }],
}>()
const settingStore = useSettingStore()
const listRef: any = $ref()
function scrollViewToCenter(index: number) {
if (index === -1) return
listRef.scrollToIndex(index)
// listRef.children[index]?.scrollIntoView({block: 'center', behavior: 'smooth'})
}
watch(() => props.activeIndex, (n: any) => {
if (settingStore.showPanel) {
scrollViewToCenter(n)
}
})
watch(() => props.isActive, (n: boolean) => {
setTimeout(() => {
if (n) scrollViewToCenter(props.activeIndex)
}, 300)
})
// watch(() => props.list, () => {
// listRef.scrollTo(0, 0)
// })
const playWordAudio = usePlayWordAudio()
function reset() {
listRef.reset()
}
function scrollToBottom() {
listRef.scrollToIndex(props.list.length - 1)
}
defineExpose({scrollToBottom})
</script>
<template>
<virtual-list class="virtual-list"
:keeps="20"
data-key="name"
:data-sources="list"
:estimate-size="85"
ref="listRef"
>
<template #={source,index}>
<div class="common-list-item space15"
:class="{active:activeIndex === index}"
@click="emit('change',{word:source,index})"
>
<div class="left">
<div class="title-wrapper">
<div class="item-title">
<span class="word" :class="!showWord && 'text-shadow'">{{ source.name }}</span>
<span class="phonetic">{{ source.usphone }}</span>
<VolumeIcon class="volume" @click="playWordAudio(source.name)"></VolumeIcon>
</div>
<div class="item-sub-title" v-if="source.trans.length && showTranslate">
<div v-for="item in source.trans">{{ item }}</div>
</div>
</div>
</div>
<div class="right">
<slot :word="source" :index="index"></slot>
</div>
</div>
</template>
</virtual-list>
</template>
<style lang="scss" scoped>
@import "@/assets/css/variable";
.virtual-list {
overflow: overlay;
height: 100%;
padding: 0 var(--space);
}
</style>

View File

@@ -1,121 +0,0 @@
<script setup lang="ts">
import {Word} from "../../types.ts";
import {useSettingStore} from "@/stores/setting.ts";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {usePlayWordAudio} from "@/hooks/sound.ts";
import {watch} from 'vue'
const props = withDefaults(defineProps<{
list: Word[],
activeIndex?: number,
isActive?: boolean
showTranslate?: boolean
showWord?: boolean
}>(), {
activeIndex: -1,
isActive: false,
showTranslate: true,
showWord: true
})
const emit = defineEmits<{
click: [val: { word: Word, index: number }],
}>()
const settingStore = useSettingStore()
const listRef: any = $ref()
function scrollViewToCenter(index: number) {
if (index === -1) return
listRef.scrollToIndex(index)
// listRef.children[index]?.scrollIntoView({block: 'center', behavior: 'smooth'})
}
watch(() => props.activeIndex, (n: any) => {
if (settingStore.showPanel) {
scrollViewToCenter(n)
}
})
watch(() => props.isActive, (n: boolean) => {
setTimeout(() => {
if (n) scrollViewToCenter(props.activeIndex)
}, 300)
})
// watch(() => props.list, () => {
// listRef.scrollTo(0, 0)
// })
const playWordAudio = usePlayWordAudio()
function reset() {
listRef.reset()
}
function scrollToBottom() {
listRef.scrollToBottom()
}
function scrollToItem(index: number) {
listRef.scrollToItem(index)
}
defineExpose({scrollToBottom, scrollToItem})
</script>
<template>
<DynamicScroller
:items="list"
ref="listRef"
:min-item-size="90"
class="scroller"
>
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[
item.id,
]"
:data-index="index"
>
<div class="list-item-wrapper">
<div class="common-list-item"
:class="{active:activeIndex === index}"
@click="emit('click',{word:item,index})"
>
<div class="left">
<slot name="prefix" :word="item" :index="index"></slot>
<div class="title-wrapper">
<div class="item-title">
<span class="word" :class="!showWord && 'text-shadow'">{{ item.name }}</span>
<span class="phonetic">{{ item.usphone }}</span>
<VolumeIcon class="volume" @click="playWordAudio(item.name)"></VolumeIcon>
</div>
<div class="item-sub-title" v-if="item.trans.length && showTranslate">
<div v-for="tran in item.trans">{{ tran }}</div>
</div>
</div>
</div>
<div class="right">
<slot :word="item" :index="index"></slot>
</div>
</div>
</div>
</DynamicScrollerItem>
</template>
</DynamicScroller>
</template>
<style lang="scss" scoped>
@import "@/assets/css/variable";
.scroller {
height: 100%;
padding: 0 var(--space);
}
</style>

View File

@@ -1,11 +0,0 @@
<script setup lang="ts">
</script>
<template>
</template>
<style scoped lang="scss">
</style>

View File

@@ -2,11 +2,7 @@
import Input from "@/components/Input.vue";
import {$computed, $ref} from "vue/macros";
import {Article, Word} from "@/types.ts";
import ListItem from "@/components/list/ListItem.vue";
import {useSettingStore} from "@/stores/setting.ts";
import {onMounted, useAttrs, watch} from "vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import {Article} from "@/types.ts";
import BaseList from "@/components/list2/BaseList.vue";
const props = withDefaults(defineProps<{