Optimize UI interface
This commit is contained in:
@@ -11,22 +11,19 @@ interface IProps {
|
||||
type?: 'primary' | 'link'
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
withDefaults(defineProps<IProps>(), {
|
||||
type: 'primary',
|
||||
size: 'normal',
|
||||
})
|
||||
|
||||
defineEmits(['click'])
|
||||
|
||||
function click() {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Tooltip :disabled="!keyboard" :title="`快捷键: ${keyboard}`">
|
||||
<div class="base-button"
|
||||
@click="(!disabled && !loading) && $emit('click')"
|
||||
@click="e => (!disabled && !loading) && $emit('click',e)"
|
||||
:class="[
|
||||
active && 'active',
|
||||
size,
|
||||
@@ -113,7 +110,8 @@ function click() {
|
||||
&.link {
|
||||
border-radius: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
&:hover{
|
||||
|
||||
&:hover {
|
||||
border-bottom: 2px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
29
src/components/Empty.vue
Normal file
29
src/components/Empty.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
text?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="empty">
|
||||
<img src="@/assets/img/缺省页_空白页-通用.svg" alt="">
|
||||
<span>{{ text ?? '空荡荡的~'}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.empty {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
font-size: 12rem;
|
||||
gap: 20rem;
|
||||
|
||||
img {
|
||||
width: 120rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -33,11 +33,18 @@ export default {
|
||||
methods: {
|
||||
showPop(e) {
|
||||
if (this.disabled) return
|
||||
e.stopPropagation()
|
||||
e?.stopPropagation()
|
||||
let rect = e.target.getBoundingClientRect()
|
||||
this.show = true
|
||||
nextTick(() => {
|
||||
this.$refs.tip.style.top = rect.top + 'px'
|
||||
let tip = this.$refs?.tip?.getBoundingClientRect()
|
||||
console.log('rect', rect, tip)
|
||||
if (!tip) return
|
||||
if (rect.top < 150) {
|
||||
this.$refs.tip.style.top = rect.top + rect.height + tip.height + 30 + 'px'
|
||||
} else {
|
||||
this.$refs.tip.style.top = rect.top - 10 + 'px'
|
||||
}
|
||||
this.$refs.tip.style.left = rect.left + rect.width / 2 - 50 + 'px'
|
||||
})
|
||||
},
|
||||
@@ -98,8 +105,8 @@ $bg-color: rgb(226, 226, 226);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
font-size: 10rem;
|
||||
gap: 12rem;
|
||||
font-size: 12rem;
|
||||
|
||||
div {
|
||||
cursor: pointer;
|
||||
@@ -108,8 +115,8 @@ $bg-color: rgb(226, 226, 226);
|
||||
.main {
|
||||
color: gray;
|
||||
background: $bg-color;
|
||||
padding: 3rem 8rem;
|
||||
border-radius: 2rem;
|
||||
padding: 3rem 10rem;
|
||||
border-radius: 4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import PopConfirm from "@/components/PopConfirm.vue"
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Close from "@/components/Close.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import ArticleList from "@/components/Article/ArticleList.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
@@ -31,10 +33,13 @@ watch(() => settingStore.showPanel, n => {
|
||||
}
|
||||
})
|
||||
|
||||
let practiceType = $ref(DictType.word)
|
||||
|
||||
function changeIndex(i: number, dict: Dict) {
|
||||
store.changeDict(dict, dict.chapterIndex, i)
|
||||
store.changeDict(dict, dict.chapterIndex, i,practiceType)
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<Transition name="fade">
|
||||
@@ -58,69 +63,84 @@ function changeIndex(i: number, dict: Dict) {
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.collect.words.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,store.collect)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 1"
|
||||
:list="store.collect.words"
|
||||
:activeIndex="-1"/>
|
||||
<div class="panel-page-item">
|
||||
<header>
|
||||
<div class="left">
|
||||
<el-radio-group v-model="practiceType">
|
||||
<el-radio-button border :label="DictType.word">单词</el-radio-button>
|
||||
<el-radio-button border :label="DictType.article">文章</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div class="dict-name" v-if="practiceType === DictType.word">{{ store.collect.words.length }}个单词</div>
|
||||
<div class="dict-name" v-else> {{ store.collect.articles.length }}篇文章</div>
|
||||
</div>
|
||||
<template v-if="store.current.dictType !== DictType.collect &&
|
||||
(
|
||||
( practiceType === DictType.word && store.collect.words.length) ||
|
||||
( practiceType === DictType.article && store.collect.articles.length)
|
||||
)">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.collect)"
|
||||
>
|
||||
<BaseButton size="small">切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</template>
|
||||
</header>
|
||||
<template v-if="practiceType === DictType.word">
|
||||
<WordList
|
||||
v-if="store.collect.words.length"
|
||||
class="word-list"
|
||||
:list="store.collect.words"/>
|
||||
<Empty v-else/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ArticleList
|
||||
v-if="store.collect.articles.length"
|
||||
style="padding: 0 20rem;"
|
||||
:select-item="{id: ''} as any"
|
||||
v-model:list="store.collect.articles"/>
|
||||
<Empty v-else/>
|
||||
</template>
|
||||
</div>
|
||||
<footer v-if="store.current.dictType !== DictType.collect && store.collect.words.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.collect)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<a href="" target="_blank"></a>
|
||||
<div class="dict-name">总词数:{{ store.wrong.words.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="panel-page-item" v-if="store.wrong.words.length">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.wrong.words.length }}</div>
|
||||
<template
|
||||
v-if="store.current.dictType !== DictType.wrong && store.wrong.words.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.wrong)"
|
||||
>
|
||||
<BaseButton size="small">切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</template>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,store.wrong)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 2"
|
||||
:list="store.wrong.words"
|
||||
:activeIndex="-1"/>
|
||||
:list="store.wrong.words"/>
|
||||
</div>
|
||||
<footer
|
||||
v-if="store.current.dictType !== DictType.wrong && store.wrong.words.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.wrong)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
<Empty v-else/>
|
||||
</div>
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.skip.words.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="panel-page-item" v-if="store.skip.words.length">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ store.skip.words.length }}</div>
|
||||
<template v-if="store.current.dictType !== DictType.skip && store.skip.words.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.skip)"
|
||||
>
|
||||
<BaseButton size="small">切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</template>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,store.skip)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 3"
|
||||
:list="store.skip.words"
|
||||
:activeIndex="-1"/>
|
||||
:list="store.skip.words"/>
|
||||
</div>
|
||||
<footer v-if="store.current.dictType !== DictType.skip && store.skip.words.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.skip)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
<Empty v-else/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -158,7 +178,7 @@ $header-height: 50rem;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10rem;
|
||||
font-size: 18rem;
|
||||
font-size: 16rem;
|
||||
color: black;
|
||||
}
|
||||
|
||||
@@ -170,7 +190,7 @@ $header-height: 50rem;
|
||||
|
||||
footer {
|
||||
padding-right: $space;
|
||||
height: 50rem;
|
||||
margin-bottom: 10rem;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,17 @@ import ArticleList from "@/components/Article/ArticleList.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
|
||||
const store = useBaseStore()
|
||||
const practiceStore = usePracticeStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
|
||||
let tabIndex = $ref(0)
|
||||
let wordData = $ref({
|
||||
words: [],
|
||||
index: -1
|
||||
})
|
||||
let index = $ref(0)
|
||||
let articleData = $ref({
|
||||
article: cloneDeep(DefaultArticle),
|
||||
sectionIndex: 0,
|
||||
@@ -235,20 +236,20 @@ function nextWord(word: ArticleWord) {
|
||||
<div class="panel-wrapper">
|
||||
<Panel
|
||||
v-if="tabIndex === 0">
|
||||
<div class="current-practice-dict">
|
||||
<div class="panel-page-item">
|
||||
<header>
|
||||
<div class="left">
|
||||
<Tooltip title="切换词典">
|
||||
<IconWrapper>
|
||||
<Icon icon="basil:exchange-outline"/>
|
||||
<Icon @click="runtimeStore.showDictModal = true" icon="basil:exchange-outline"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<div class="title">
|
||||
{{ store.currentDict.name + ` 第${store.currentDict.chapterIndex + 1}章` }}
|
||||
{{ store.dictTitle }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
共{{ store.currentDict.articles.length }}章
|
||||
{{ store.currentDict.articles.length }}篇文章
|
||||
</div>
|
||||
</header>
|
||||
<ArticleList :select-item="articleData.article"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import WordPanel from "@/components/Practice/PracticeWord/WordPanel.vue";
|
||||
import TypingWord from "@/components/Practice/PracticeWord/TypingWord.vue";
|
||||
import {$ref} from "vue/macros";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
|
||||
@@ -12,11 +12,10 @@ 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 WordPanel from "@/components/Practice/PracticeWord/WordPanel.vue";
|
||||
import ArticleList from "@/components/Article/ArticleList.vue";
|
||||
import Panel from "@/components/Practice/Panel.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import WordList from "@/components/WordList.vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
|
||||
interface IProps {
|
||||
words: Word[],
|
||||
@@ -37,6 +36,7 @@ let data = $ref({
|
||||
|
||||
let typingRef: any = $ref()
|
||||
const store = useBaseStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const practiceStore = usePracticeStore()
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
@@ -200,7 +200,6 @@ useOnKeyboardEventListener(onKeyDown, onKeyUp)
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Typing
|
||||
v-if="false"
|
||||
ref="typingRef"
|
||||
:word="word"
|
||||
@wrong="wordWrong"
|
||||
@@ -213,25 +212,26 @@ useOnKeyboardEventListener(onKeyDown, onKeyUp)
|
||||
/>
|
||||
<div class="word-panel-wrapper">
|
||||
<Panel>
|
||||
<div class="current-practice-dict">
|
||||
<div class="panel-page-item">
|
||||
<header>
|
||||
<div class="left">
|
||||
<Tooltip title="切换词典">
|
||||
<IconWrapper>
|
||||
<Icon icon="basil:exchange-outline"/>
|
||||
<Icon @click="runtimeStore.showDictModal = true" icon="basil:exchange-outline"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<div class="title">
|
||||
{{ store.currentDict.name + ` 第${store.currentDict.chapterIndex + 1}章` }}
|
||||
{{ store.dictTitle }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
共{{ data.words.length }}词
|
||||
{{ data.words.length }}个单词
|
||||
</div>
|
||||
</header>
|
||||
<WordList
|
||||
class="word-list"
|
||||
:is-active="true"
|
||||
@change="(i:number) => data.index = i"
|
||||
:list="data.words"
|
||||
:activeIndex="data.index"/>
|
||||
</div>
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import WordList from "@/components/WordList.vue"
|
||||
|
||||
import {$computed, $ref} from "vue/macros"
|
||||
import {computed, provide, watch} from "vue"
|
||||
import {Dict, DictType, Word} from "@/types.ts"
|
||||
import PopConfirm from "@/components/PopConfirm.vue"
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Close from "@/components/Close.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
list?: Word[],
|
||||
index: number
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
'update:index': [i: number]
|
||||
}>()
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
let tabIndex = $ref(0)
|
||||
provide('tabIndex', computed(() => tabIndex))
|
||||
|
||||
watch(() => settingStore.showPanel, n => {
|
||||
if (n) {
|
||||
switch (store.current.dictType) {
|
||||
case DictType.collect:
|
||||
return tabIndex = 1;
|
||||
case DictType.skip:
|
||||
return tabIndex = 3;
|
||||
case DictType.wrong:
|
||||
return tabIndex = 2;
|
||||
case DictType.word:
|
||||
case DictType.customWord:
|
||||
return tabIndex = 0;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const currentDict: Dict = $computed(() => {
|
||||
return store.myDicts[store.current.index]
|
||||
})
|
||||
|
||||
const currentData = $computed(() => {
|
||||
if (store.current.dictType !== currentDict.type) return {
|
||||
list: currentDict.chapterWords[currentDict.chapterIndex] ?? [],
|
||||
index: -1
|
||||
}
|
||||
else return props
|
||||
})
|
||||
|
||||
const newData = $computed(() => {
|
||||
if (store.current.dictType !== DictType.collect) return {list: store.collect.words ?? [], index: -1}
|
||||
else return props
|
||||
})
|
||||
|
||||
const wrongData = $computed(() => {
|
||||
if (store.current.dictType !== DictType.wrong) return {list: store.wrong.words ?? [], index: -1}
|
||||
else return props
|
||||
})
|
||||
|
||||
const skipData = $computed(() => {
|
||||
if (store.current.dictType !== DictType.skip) return {list: store.skip.words ?? [], index: -1}
|
||||
else return props
|
||||
})
|
||||
|
||||
function changeIndex(i: number, dict: Dict) {
|
||||
dict.wordIndex = i
|
||||
console.log('i', i, dict.type)
|
||||
if (store.current.dictType === dict.type) {
|
||||
emit('update:index', i)
|
||||
} else {
|
||||
store.changeDict(dict, dict.chapterIndex, i)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<Transition name="fade">
|
||||
<div class="panel" v-if="settingStore.showPanel">
|
||||
<header>
|
||||
<Transition name="fade">
|
||||
<Close
|
||||
@click="settingStore.showPanel = false"
|
||||
v-if="!settingStore.showToolbar"/>
|
||||
</Transition>
|
||||
<div class="tabs">
|
||||
<div class="tab current" :class="tabIndex === 0 && 'active'" @click="tabIndex = 0">
|
||||
{{ currentDict.name + ` 第${currentDict.chapterIndex + 1}章` }}
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 1 && 'active'" @click="tabIndex = 1">{{ store.collect.name }}</div>
|
||||
<div class="tab" :class="tabIndex === 2 && 'active'" @click="tabIndex = 2">
|
||||
{{ store.wrong.name }}
|
||||
</div>
|
||||
<div class="tab" :class="tabIndex === 3 && 'active'" @click="tabIndex = 3">{{ store.skip.name }}</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="slide">
|
||||
<div class="slide-list" :class="`step${tabIndex}`">
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<div class="dict-name">词数:{{ currentData.list.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,currentDict)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 0"
|
||||
:list="currentData.list"
|
||||
:activeIndex="currentData.index"/>
|
||||
</div>
|
||||
<footer v-if="![DictType.customWord,DictType.word].includes(store.current.dictType)">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,currentDict)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ newData.list.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,store.collect)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 1"
|
||||
:list="newData.list"
|
||||
:activeIndex="newData.index"/>
|
||||
</div>
|
||||
<footer v-if="store.current.dictType !== DictType.collect && newData.list.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.collect)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<a href="" target="_blank"></a>
|
||||
<div class="dict-name">总词数:{{ wrongData.list.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,store.wrong)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 2"
|
||||
:list="wrongData.list"
|
||||
:activeIndex="wrongData.index"/>
|
||||
</div>
|
||||
<footer
|
||||
v-if="store.current.dictType !== DictType.wrong && wrongData.list.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.wrong)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<div class="dict-name">总词数:{{ skipData.list.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<WordList
|
||||
class="word-list"
|
||||
@change="(i:number) => changeIndex(i,store.skip)"
|
||||
:isActive="settingStore.showPanel && tabIndex === 3"
|
||||
:list="skipData.list"
|
||||
:activeIndex="skipData.index"/>
|
||||
</div>
|
||||
<footer v-if="store.current.dictType !== DictType.skip && skipData.list.length">
|
||||
<PopConfirm
|
||||
:title="`确认切换?`"
|
||||
@confirm="changeIndex(0,store.skip)"
|
||||
>
|
||||
<BaseButton>切换</BaseButton>
|
||||
</PopConfirm>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
@import "@/assets/css/variable.scss";
|
||||
|
||||
$width: 20vw;
|
||||
$header-height: 50rem;
|
||||
|
||||
.slide {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
|
||||
.slide-list {
|
||||
width: 400%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
transition: all .5s;
|
||||
|
||||
.slide-item {
|
||||
width: $width;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> header {
|
||||
padding: 0 $space;
|
||||
height: $header-height;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 10rem;
|
||||
font-size: 18rem;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding-bottom: $space;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding-right: $space;
|
||||
height: 50rem;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step1 {
|
||||
transform: translate3d(-25%, 0, 0);
|
||||
}
|
||||
|
||||
.step2 {
|
||||
transform: translate3d(-50%, 0, 0);
|
||||
}
|
||||
|
||||
.step3 {
|
||||
transform: translate3d(-75%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.panel {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 10rem;
|
||||
border-radius: 8rem;
|
||||
margin-left: calc(50% + (var(--toolbar-width) / 2) + $space);
|
||||
width: $width;
|
||||
background: var(--color-second-bg);
|
||||
height: calc(100% - 20rem);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: all .3s;
|
||||
z-index: 1;
|
||||
|
||||
& > header {
|
||||
min-height: 50rem;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10rem 15rem;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
gap: 15rem;
|
||||
|
||||
.close {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15rem;
|
||||
font-size: 14rem;
|
||||
color: gray;
|
||||
|
||||
.tab {
|
||||
cursor: pointer;
|
||||
word-break: keep-all;
|
||||
font-size: 16rem;
|
||||
|
||||
&.active {
|
||||
color: rgb(36, 127, 255);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.current {
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -179,7 +179,7 @@ const dictIsArticle = $computed(() => {
|
||||
<div class="translate">
|
||||
<span>翻译:</span>
|
||||
<el-radio-group v-model="currentTranslateLanguage">
|
||||
<el-radio border v-for="i in translateLanguageList" :label="i">{{ i }}</el-radio>
|
||||
<el-radio-button border v-for="i in translateLanguageList" :label="i">{{ i }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<DictGroup
|
||||
@@ -416,6 +416,8 @@ $header-height: 60rem;
|
||||
padding-right: $space;
|
||||
|
||||
.translate {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: black;
|
||||
margin-bottom: 30rem;
|
||||
|
||||
|
||||
@@ -17,15 +17,16 @@ import TranslateSetting from "@/components/Toolbar/TranslateSetting.vue";
|
||||
import Add from "@/components/Toolbar/Add.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
|
||||
const {toggle} = useTheme()
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const practiceStore = usePracticeStore()
|
||||
|
||||
const showFeedbackModal = $ref(false)
|
||||
const showSettingModal = $ref(false)
|
||||
const showDictModal = $ref(false)
|
||||
const headerRef = $ref<HTMLDivElement>(null)
|
||||
|
||||
watch(() => settingStore.showToolbar, n => {
|
||||
@@ -43,7 +44,7 @@ watch(() => settingStore.showToolbar, n => {
|
||||
<template>
|
||||
<header ref="headerRef">
|
||||
<div class="content">
|
||||
<div class="info" @click="showDictModal = true">
|
||||
<div class="info" @click="runtimeStore.showDictModal = true">
|
||||
{{ store.dictTitle }} {{ practiceStore.repeatNumber ? ' 复习错词' : '' }}
|
||||
</div>
|
||||
<div class="options">
|
||||
@@ -112,7 +113,7 @@ watch(() => settingStore.showToolbar, n => {
|
||||
color="#999"/>
|
||||
</Tooltip>
|
||||
</header>
|
||||
<DictModal :model-value="showDictModal" @close="showDictModal = false"/>
|
||||
<DictModal :model-value="runtimeStore.showDictModal" @close="runtimeStore.showDictModal = false"/>
|
||||
<SettingModal v-if="showSettingModal" @close="showSettingModal = false"/>
|
||||
<FeedbackModal v-if="showFeedbackModal" @close="showFeedbackModal = false"/>
|
||||
</template>
|
||||
|
||||
@@ -9,11 +9,14 @@ const emit = defineEmits<{
|
||||
del: [i: number],
|
||||
change: [i: number]
|
||||
}>()
|
||||
const props = defineProps<{
|
||||
const props = withDefaults(defineProps<{
|
||||
list: Word[],
|
||||
activeIndex: number,
|
||||
isActive: boolean
|
||||
}>()
|
||||
activeIndex?: number,
|
||||
isActive?: boolean
|
||||
}>(), {
|
||||
activeIndex: -1,
|
||||
isActive: false
|
||||
})
|
||||
|
||||
const listRef: HTMLElement = $ref(null as any)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user