rename files
This commit is contained in:
24
components.d.ts
vendored
24
components.d.ts
vendored
@@ -8,7 +8,8 @@ export {}
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
Add: typeof import('./src/components/Toolbar/Add.vue')['default']
|
||||
ArticleList: typeof import('./src/components/Article/ArticleList.vue')['default']
|
||||
ArticleList2: typeof import('./src/components/list/ArticleList2.vue')['default']
|
||||
ArticleListFQ: typeof import('./src/components/article/ArticleList-FQ.vue')['default']
|
||||
Backgorund: typeof import('./src/components/Backgorund.vue')['default']
|
||||
BaseButton: typeof import('./src/components/BaseButton.vue')['default']
|
||||
BaseIcon: typeof import('./src/components/BaseIcon.vue')['default']
|
||||
@@ -17,12 +18,10 @@ declare module 'vue' {
|
||||
Close: typeof import('./src/components/icon/Close.vue')['default']
|
||||
CommonWordList: typeof import('./src/components/list/CommonWordList.vue')['default']
|
||||
Dialog: typeof import('./src/components/dialog/Dialog.vue')['default']
|
||||
DictDialog: typeof import('./src/components/Modal/DictDialog/index.vue')['default']
|
||||
DictDiglog: typeof import('./src/components/dialog/DictDiglog.vue')['default']
|
||||
DictGroup: typeof import('./src/components/Toolbar/DictGroup.vue')['default']
|
||||
DictItem: typeof import('./src/components/list/DictItem.vue')['default']
|
||||
DictList: typeof import('./src/components/list/DictList.vue')['default']
|
||||
DictModal2: typeof import('./src/components/Modal/DictModal2.vue')['default']
|
||||
EditAbleText: typeof import('./src/components/EditAbleText.vue')['default']
|
||||
EditArticle: typeof import('./src/components/Article/EditArticle.vue')['default']
|
||||
EditBatchArticleModal: typeof import('./src/components/Article/EditBatchArticleModal.vue')['default']
|
||||
@@ -49,31 +48,26 @@ declare module 'vue' {
|
||||
List: typeof import('./src/components/list/List.vue')['default']
|
||||
ListItem: typeof import('./src/components/list/ListItem.vue')['default']
|
||||
MiniDialog: typeof import('./src/components/dialog/MiniDialog.vue')['default']
|
||||
MiniModal: typeof import('./src/components/Modal/MiniModal.vue')['default']
|
||||
Modal: typeof import('./src/components/dialog/Modal.vue')['default']
|
||||
Options: typeof import('./src/components/Practice/Options.vue')['default']
|
||||
Panel: typeof import('./src/components/Practice/Panel.vue')['default']
|
||||
PopConfirm: typeof import('./src/components/PopConfirm.vue')['default']
|
||||
Practice: typeof import('./src/components/Practice/Practice.vue')['default']
|
||||
PracticeArticle: typeof import('./src/components/Practice/PracticeArticle/PracticeArticle.vue')['default']
|
||||
PracticeWord: typeof import('./src/components/Practice/PracticeWord/PracticeWord.vue')['default']
|
||||
Practice: typeof import('./src/components/Practice/index.vue')['default']
|
||||
PracticeArticle: typeof import('./src/components/Practice/practice-article/index.vue')['default']
|
||||
PracticeWord: typeof import('./src/components/Practice/practice-word/index.vue')['default']
|
||||
RepeatSetting: typeof import('./src/components/Toolbar/RepeatSetting.vue')['default']
|
||||
Ring: typeof import('./src/components/Ring.vue')['default']
|
||||
SettingDialog: typeof import('./src/components/dialog/SettingDialog.vue')['default']
|
||||
SettingModal: typeof import('./src/components/dialog/SettingModal.vue')['default']
|
||||
Slide: typeof import('./src/components/Slide.vue')['default']
|
||||
Statistics: typeof import('./src/components/Practice/Statistics.vue')['default']
|
||||
Toolbar: typeof import('./src/components/Toolbar/Toolbar.vue')['default']
|
||||
Toolbar: typeof import('./src/components/toolbar/index.vue')['default']
|
||||
Tooltip: typeof import('./src/components/Tooltip.vue')['default']
|
||||
TranslateSetting: typeof import('./src/components/Toolbar/TranslateSetting.vue')['default']
|
||||
Typing: typeof import('./src/components/Practice/PracticeWord/Typing.vue')['default']
|
||||
TypingArticle: typeof import('./src/components/Practice/PracticeArticle/TypingArticle.vue')['default']
|
||||
TypingWord: typeof import('./src/components/Practice/PracticeWord/TypingWord.vue')['default']
|
||||
Typing: typeof import('./src/components/Practice/practice-word/Typing.vue')['default']
|
||||
TypingArticle: typeof import('./src/components/Practice/practice-article/TypingArticle.vue')['default']
|
||||
TypingWord: typeof import('./src/components/Practice/practice-word/TypingWord.vue')['default']
|
||||
VirtualWordList: typeof import('./src/components/list/VirtualWordList.vue')['default']
|
||||
VolumeIcon: typeof import('./src/components/icon/VolumeIcon.vue')['default']
|
||||
VolumeSetting: typeof import('./src/components/Toolbar/VolumeSetting.vue')['default']
|
||||
WordItem: typeof import('./src/components/list/WordItem.vue')['default']
|
||||
WordList: typeof import('./src/components/list/WordList.vue')['default']
|
||||
WordListDialog: typeof import('./src/components/dialog/WordListDialog.vue')['default']
|
||||
}
|
||||
export interface ComponentCustomProperties {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import {onMounted, watch} from "vue";
|
||||
import {BaseState, useBaseStore} from "@/stores/base.ts";
|
||||
import {DictType, SaveConfig, SaveDict} from "@/types.ts"
|
||||
import Practice from "@/components/Practice/Practice.vue"
|
||||
import Practice from "@/components/Practice/index.vue"
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
|
||||
@@ -73,7 +73,7 @@ function toggle() {
|
||||
}
|
||||
|
||||
.text {
|
||||
color: black;
|
||||
color: var(--color-font-1);
|
||||
min-height: 18rem;
|
||||
}
|
||||
</style>
|
||||
@@ -134,8 +134,6 @@ onUnmounted(() => {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
:deep(.el-progress-bar__inner) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import WordList from "@/components/list/WordList.vue"
|
||||
|
||||
import {$ref} from "vue/macros"
|
||||
import {computed, onMounted, provide, watch} from "vue"
|
||||
@@ -10,14 +9,15 @@ import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Close from "@/components/icon/Close.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import ArticleList from "@/components/Article/ArticleList.vue";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
import ArticleList from "@/components/article/ArticleList-FQ.vue";
|
||||
import {useArticleOptions, useWordOptions} from "@/hooks/dict.ts";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import CommonWordList from "@/components/list/CommonWordList.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import ArticleList2 from "@/components/list/ArticleList2.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
@@ -48,6 +48,10 @@ const {
|
||||
toggleWordCollect,
|
||||
} = useWordOptions()
|
||||
|
||||
const {
|
||||
isArticleCollect,
|
||||
toggleArticleCollect
|
||||
} = useArticleOptions()
|
||||
|
||||
</script>
|
||||
<template>
|
||||
@@ -123,11 +127,19 @@ const {
|
||||
<Empty v-else/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ArticleList
|
||||
<ArticleList2
|
||||
v-if="store.collect.articles.length"
|
||||
style="padding: 0 20rem;"
|
||||
:select-item="{id: ''} as any"
|
||||
v-model:list="store.collect.articles"/>
|
||||
:show-translate="true"
|
||||
v-model:list="store.collect.articles">
|
||||
<template v-slot="{source,index}">
|
||||
<BaseIcon
|
||||
class-name="del"
|
||||
@click="toggleArticleCollect(source)"
|
||||
title="移除"
|
||||
icon="solar:trash-bin-minimalistic-linear"/>
|
||||
</template>
|
||||
</ArticleList2>
|
||||
|
||||
<Empty v-else/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Toolbar from "@/components/toolbar/Toolbar.vue"
|
||||
import Toolbar from "@/components/toolbar/index.vue"
|
||||
import {onMounted, onUnmounted, watch} from "vue";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import Footer from "@/components/Practice/Footer.vue";
|
||||
@@ -11,8 +11,8 @@ import {emitter, EventKey} from "@/utils/eventBus";
|
||||
import {useSettingStore} from "@/stores/setting";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import PracticeArticle from "@/components/Practice/PracticeArticle/PracticeArticle.vue";
|
||||
import PracticeWord from "@/components/Practice/PracticeWord/PracticeWord.vue";
|
||||
import PracticeArticle from "@/components/Practice/practice-article/index.vue";
|
||||
import PracticeWord from "@/components/Practice/practice-word/index.vue";
|
||||
import {ShortcutKey} from "@/types.ts";
|
||||
import useTheme from "@/hooks/useTheme.ts";
|
||||
import SettingDialog from "@/components/dialog/SettingDialog.vue";
|
||||
@@ -14,6 +14,7 @@ import {Icon} from "@iconify/vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {useArticleOptions} from "@/hooks/dict.ts";
|
||||
|
||||
interface IProps {
|
||||
article: Article,
|
||||
@@ -371,6 +372,11 @@ function toggleCollect() {
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
isArticleCollect,
|
||||
toggleArticleCollect
|
||||
} = useArticleOptions()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -386,15 +392,15 @@ function toggleCollect() {
|
||||
@click="emit('edit',props.article)"
|
||||
/>
|
||||
<BaseIcon
|
||||
v-if="!false"
|
||||
v-if="!isArticleCollect(props.article)"
|
||||
class-name="collect"
|
||||
@click="$emit('toggleCollect')"
|
||||
@click="toggleArticleCollect(props.article)"
|
||||
:title="`收藏(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.ToggleCollect]})`"
|
||||
icon="ph:star"/>
|
||||
<BaseIcon
|
||||
v-else
|
||||
class-name="fill"
|
||||
@click="toggleCollect"
|
||||
@click="toggleArticleCollect(props.article)"
|
||||
:title="`取消收藏(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.ToggleCollect]})`"
|
||||
icon="ph:star-fill"/>
|
||||
<BaseIcon
|
||||
@@ -12,21 +12,24 @@ import {
|
||||
Word
|
||||
} from "@/types.ts";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import TypingWord from "@/components/Practice/PracticeWord/TypingWord.vue";
|
||||
import TypingWord from "@/components/Practice/practice-word/TypingWord.vue";
|
||||
import Panel from "../Panel.vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import {renewSectionTexts, renewSectionTranslates} from "@/hooks/translate.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import EditSingleArticleModal from "@/components/Article/EditSingleArticleModal.vue";
|
||||
import EditSingleArticleModal from "@/components/article/EditSingleArticleModal.vue";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import ArticleList from "@/components/Article/ArticleList.vue";
|
||||
import ArticleList from "@/components/article/ArticleList-FQ.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import ArticleList2 from "@/components/list/ArticleList2.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {useArticleOptions} from "@/hooks/dict.ts";
|
||||
|
||||
const store = useBaseStore()
|
||||
const practiceStore = usePracticeStore()
|
||||
@@ -225,6 +228,10 @@ function changePracticeArticle(val: Article) {
|
||||
defineExpose({getCurrentPractice})
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
const {
|
||||
isArticleCollect,
|
||||
toggleArticleCollect
|
||||
} = useArticleOptions()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -279,11 +286,25 @@ const settingStore = useSettingStore()
|
||||
{{ store.currentDict.articles.length }}篇文章
|
||||
</div>
|
||||
</div>
|
||||
<ArticleList
|
||||
<ArticleList2
|
||||
:isActive="active"
|
||||
:show-translate="settingStore.translate"
|
||||
@select-item="changePracticeArticle"
|
||||
:active-index="store.currentDict.chapterIndex"
|
||||
v-model:list="store.currentDict.articles"/>
|
||||
v-model:list="store.currentDict.articles">
|
||||
<template v-slot="{source,index}">
|
||||
<BaseIcon
|
||||
v-if="!isArticleCollect(source)"
|
||||
class-name="collect"
|
||||
@click="toggleArticleCollect(source)"
|
||||
title="收藏" icon="ph:star"/>
|
||||
<BaseIcon
|
||||
v-else
|
||||
class-name="fill"
|
||||
@click="toggleArticleCollect(source)"
|
||||
title="取消收藏" icon="ph:star-fill"/>
|
||||
</template>
|
||||
</ArticleList2>
|
||||
</div>
|
||||
</template>
|
||||
</Panel>
|
||||
@@ -2,15 +2,7 @@
|
||||
import {onMounted, onUnmounted, watch} from "vue"
|
||||
import {$computed, $ref} from "vue/macros"
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import {
|
||||
DefaultDisplayStatistics,
|
||||
DefaultShortcutKeyMap,
|
||||
DictType,
|
||||
DisplayStatistics,
|
||||
ShortcutKey,
|
||||
ShortcutKeyMap,
|
||||
Word
|
||||
} from "../../../types";
|
||||
import {DefaultDisplayStatistics, DictType, ShortcutKey, Word} from "../../../types";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
import {cloneDeep} from "lodash-es"
|
||||
import {usePracticeStore} from "@/stores/practice.ts"
|
||||
@@ -19,13 +11,11 @@ import {useOnKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import Options from "@/components/Practice/Options.vue";
|
||||
import Typing from "@/components/Practice/PracticeWord/Typing.vue";
|
||||
import Typing from "@/components/Practice/practice-word/Typing.vue";
|
||||
import Panel from "@/components/Practice/Panel.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import WordList from "@/components/list/WordList.vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import CommonWordList from "@/components/list/CommonWordList.vue";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import TypingWord from "@/components/Practice/PracticeWord/TypingWord.vue";
|
||||
import TypingWord from "@/components/Practice/practice-word/TypingWord.vue";
|
||||
import {$ref} from "vue/macros";
|
||||
import {chunk, cloneDeep} from "lodash-es";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
@@ -436,9 +436,10 @@ defineExpose({save, getEditArticle: () => cloneDeep(editArticle)})
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
border-radius: 8rem;
|
||||
background: var(--color-main-bg);
|
||||
|
||||
.section {
|
||||
background: white;
|
||||
background: var(--color-item-bg);
|
||||
margin-bottom: 20rem;
|
||||
padding: var(--space);
|
||||
border-radius: 8rem;
|
||||
@@ -466,7 +467,6 @@ defineExpose({save, getEditArticle: () => cloneDeep(editArticle)})
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -10,7 +10,7 @@ import {$computed, $ref} from "vue/macros";
|
||||
import List from "@/components/list/List.vue";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import Dialog from "@/components/dialog/Dialog.vue";
|
||||
import EditArticle from "@/components/Article/EditArticle.vue";
|
||||
import EditArticle from "@/components/article/EditArticle.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {useDisableEventListener} from "@/hooks/event.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
@@ -300,7 +300,7 @@ function saveAndNext(val: Article) {
|
||||
|
||||
.slide {
|
||||
height: 100%;
|
||||
background: white;
|
||||
background: var(--color-main-bg);
|
||||
padding: 0 10rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -316,7 +316,7 @@ function saveAndNext(val: Article) {
|
||||
|
||||
.dict-name {
|
||||
font-size: 30rem;
|
||||
color: black;
|
||||
color: var(--color-font-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ function saveAndNext(val: Article) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
transition: all .3s;
|
||||
color: white;
|
||||
color: var(--color-font-1);
|
||||
background: var(--color-item-active);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import {Article, DefaultArticle} from "@/types.ts";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import Dialog from "@/components/dialog/Dialog.vue";
|
||||
import EditArticle from "@/components/Article/EditArticle.vue";
|
||||
import EditArticle from "@/components/article/EditArticle.vue";
|
||||
|
||||
interface IProps {
|
||||
article?: Article
|
||||
@@ -24,7 +24,7 @@ import {FormInstance, FormRules} from "element-plus";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Dialog from "@/components/dialog/Dialog.vue";
|
||||
import EditBatchArticleModal from "@/components/Article/EditBatchArticleModal.vue";
|
||||
import EditBatchArticleModal from "@/components/article/EditBatchArticleModal.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
120
src/components/list/ArticleList2.vue
Normal file
120
src/components/list/ArticleList2.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<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="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 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>
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {Word} from "../../types.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import WordItem from "@/components/list/WordItem.vue";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {watch} from 'vue'
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {Word} from "@/types.ts";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
active?: boolean
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
word: Word
|
||||
}>(), {
|
||||
showTranslate: true,
|
||||
showWord: true
|
||||
})
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
const {
|
||||
isWordCollect,
|
||||
toggleWordCollect,
|
||||
isWordSimple,
|
||||
toggleWordSimple,
|
||||
} = useWordOptions()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="common-list-item"
|
||||
:class="{active}"
|
||||
>
|
||||
<div class="left">
|
||||
<div class="item-title">
|
||||
<span class="word" :class="!showWord && 'text-shadow'">{{ word.name }}</span>
|
||||
<span class="phonetic">{{ word.usphone }}</span>
|
||||
<VolumeIcon class="volume" @click="playWordAudio(word.name)"></VolumeIcon>
|
||||
</div>
|
||||
<div class="item-sub-title" v-if="word.trans.length && showTranslate">
|
||||
<div v-for="item in word.trans">{{ item }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.left {
|
||||
display: flex;
|
||||
gap: 10rem;
|
||||
flex-direction: column;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5rem;
|
||||
transition: all .3s;
|
||||
}
|
||||
</style>
|
||||
@@ -1,105 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import {Word} from "../../types.ts";
|
||||
import {watch} from "vue"
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import ListItem from "@/components/list/ListItem.vue";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {useWordOptions} from "@/hooks/dict.ts";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
list: Word[],
|
||||
activeIndex?: number,
|
||||
showDel?: boolean,
|
||||
isActive?: boolean
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
}>(), {
|
||||
activeIndex: -1,
|
||||
isActive: false,
|
||||
showDel: false,
|
||||
showTranslate: true,
|
||||
showWord: true
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
del: [val: Word],
|
||||
change: [i: 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()
|
||||
const {
|
||||
isWordCollect,
|
||||
toggleWordCollect,
|
||||
isWordSimple,
|
||||
toggleWordSimple,
|
||||
} = useWordOptions()
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="list" ref="listRef">
|
||||
<ListItem
|
||||
v-for="(word,i) in list" :key="i"
|
||||
class="common-list-item"
|
||||
:active="activeIndex === i"
|
||||
:class="{active:activeIndex === i}"
|
||||
:show-volume="true"
|
||||
@click="emit('change',i)"
|
||||
:isCollect="isWordCollect(word)"
|
||||
@toggle-collect="toggleWordCollect(word)"
|
||||
:is-simple="isWordSimple(word)"
|
||||
@toggle-simple="toggleWordCollect(word)"
|
||||
:show-del="showDel"
|
||||
@del="emit('del',word)"
|
||||
>
|
||||
<div class="item-title">
|
||||
<span class="word" :class="!showWord && 'text-shadow'">{{ word.name }}</span>
|
||||
<span class="phonetic">{{ word.usphone }}</span>
|
||||
<VolumeIcon class="volume" @click="playWordAudio(word.name)"></VolumeIcon>
|
||||
</div>
|
||||
<div class="item-sub-title" v-if="word.trans.length && showTranslate">
|
||||
<div v-for="item in word.trans">{{ item }}</div>
|
||||
</div>
|
||||
</ListItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/assets/css/variable";
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15rem;
|
||||
flex: 1;
|
||||
overflow: overlay;
|
||||
padding: 0 var(--space);
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Dict, DictType, Word} from "@/types.ts";
|
||||
import {Article, Dict, DictType, Word} from "@/types.ts";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {chunk, cloneDeep} from "lodash-es";
|
||||
@@ -66,6 +66,29 @@ export function useWordOptions() {
|
||||
}
|
||||
}
|
||||
|
||||
export function useArticleOptions() {
|
||||
const store = useBaseStore()
|
||||
|
||||
function isArticleCollect(val: Article) {
|
||||
return !!store.collect.articles.find(v => v.title.toLowerCase() === val.title.toLowerCase())
|
||||
}
|
||||
|
||||
function toggleArticleCollect(val: Article) {
|
||||
let rIndex = store.collect.articles.findIndex(v => v.title.toLowerCase() === val.title.toLowerCase())
|
||||
if (rIndex > -1) {
|
||||
store.collect.articles.splice(rIndex, 1)
|
||||
} else {
|
||||
store.collect.articles.push(val)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isArticleCollect,
|
||||
toggleArticleCollect,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function checkDictHasTranslate(dict: Dict) {
|
||||
let dictResourceUrl = `./dicts/${dict.language}/${dict.type}/${dict.translateLanguage}/${dict.url}`;
|
||||
if ([
|
||||
|
||||
Reference in New Issue
Block a user