Perfect panel
This commit is contained in:
2
components.d.ts
vendored
2
components.d.ts
vendored
@@ -54,6 +54,8 @@ declare module 'vue' {
|
||||
TypeWord: typeof import('./src/components/Practice/TypeWord.vue')['default']
|
||||
VolumeIcon: typeof import('./src/components/VolumeIcon.vue')['default']
|
||||
VolumeSetting: typeof import('./src/components/Toolbar/VolumeSetting.vue')['default']
|
||||
Word: typeof import('./src/components/Word.vue')['default']
|
||||
WordItem: typeof import('./src/components/WordItem.vue')['default']
|
||||
WordList: typeof import('./src/components/WordList.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,34 +36,23 @@ watch(() => settingStore.showPanel, n => {
|
||||
})
|
||||
const newWordDictActiveIndex = computed(() => {
|
||||
if (store.current.dictType !== DictType.newDict) return -1
|
||||
else {
|
||||
if (store.current.repeatNumber) {
|
||||
return store.chapter.findIndex(v => v.name === store.word.name)
|
||||
}
|
||||
return store.current.index
|
||||
}
|
||||
else return props.index
|
||||
})
|
||||
|
||||
const wrongWordDictActiveIndex = computed(() => {
|
||||
if (store.current.dictType !== DictType.wrongDict) return -1
|
||||
else {
|
||||
if (store.current.repeatNumber) {
|
||||
return store.chapter.findIndex(v => v.name === store.word.name)
|
||||
}
|
||||
return store.current.index
|
||||
}
|
||||
else return props.index
|
||||
})
|
||||
|
||||
const skipWordDictActiveIndex = computed(() => {
|
||||
if (store.current.dictType !== DictType.skipDict) return -1
|
||||
else {
|
||||
if (store.current.repeatNumber) {
|
||||
return store.chapter.findIndex(v => v.name === store.word.name)
|
||||
}
|
||||
return store.current.index
|
||||
}
|
||||
else return props.index
|
||||
})
|
||||
|
||||
function changeIndex(i: number) {
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<Transition name="fade">
|
||||
@@ -83,7 +72,7 @@ const skipWordDictActiveIndex = computed(() => {
|
||||
<div class="slide-list" :class="`step${tabIndex}`">
|
||||
<div class="slide-item">
|
||||
<header>
|
||||
<div class="dict-name">{{ store.currentDict.chapterIndex + 1 }}.</div>
|
||||
<div class="dict-name">词数:{{ props.list.length }}</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<WordList
|
||||
@@ -237,11 +226,12 @@ $header-height: 50rem;
|
||||
.panel {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
top: 10rem;
|
||||
border-radius: 8rem;
|
||||
margin-left: calc(50% + (var(--toolbar-width) / 2) + $space);
|
||||
width: $width;
|
||||
background: var(--color-second-bg);
|
||||
height: 100%;
|
||||
height: calc(100% - 40rem);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: all .3s;
|
||||
|
||||
@@ -68,7 +68,7 @@ useWatchAllSound()
|
||||
<div class="row">
|
||||
<label class="sub-title">倍速</label>
|
||||
<div class="wrapper">
|
||||
<el-slider v-model="settingStore.wordSoundSpeed" :step="0.1" :min="1" :max="4"/>
|
||||
<el-slider v-model="settingStore.wordSoundSpeed" :step="0.1" :min="0.5" :max="4"/>
|
||||
<span>{{ settingStore.wordSoundSpeed }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -114,7 +114,6 @@ header {
|
||||
width: var(--toolbar-width);
|
||||
margin-top: 10rem;
|
||||
background: var(--color-header-bg);
|
||||
|
||||
border-radius: 8rem;
|
||||
margin-bottom: 30rem;
|
||||
//position: absolute;
|
||||
|
||||
96
src/components/WordItem.vue
Normal file
96
src/components/WordItem.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import VolumeIcon from "@/components/VolumeIcon.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {Word} from "@/types.ts";
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
const props = defineProps<{
|
||||
word: Word,
|
||||
active?: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
del: []
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="word-item"
|
||||
:class="{active}">
|
||||
<div class="left">
|
||||
<div class="title">
|
||||
<span class="word">{{ word.name }}</span>
|
||||
<span class="phonetic">{{ word.usphone }}</span>
|
||||
</div>
|
||||
<div class="translate">{{ word.trans.join(';') }}</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<VolumeIcon @click="playWordAudio(word.name)"></VolumeIcon>
|
||||
<div class="del"
|
||||
@click="emit('del')"
|
||||
>
|
||||
<Icon
|
||||
icon="fluent:delete-28-regular"
|
||||
width="20"
|
||||
color="#929596"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/assets/css/colors";
|
||||
|
||||
.word-item {
|
||||
background: var(--color-header-bg);
|
||||
border-radius: 6rem;
|
||||
padding: 12rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
transition: all .3s;
|
||||
color: var(--color-font-1);
|
||||
|
||||
&.active {
|
||||
background: $second;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
//background: $dark-main-bg;
|
||||
//background: $item-hover;
|
||||
background: rgb(226, 226, 226);
|
||||
}
|
||||
|
||||
.left {
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
|
||||
.word {
|
||||
font-size: 24rem;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.phonetic {
|
||||
font-size: 14rem;
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 5rem;
|
||||
|
||||
.del {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,19 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import {Word} from "../types";
|
||||
import {watch} from "vue"
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import {Icon} from '@iconify/vue';
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import WordItem from "@/components/WordItem.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const emit = defineEmits(['change'])
|
||||
const settingStore = useSettingStore()
|
||||
const emit = defineEmits<{
|
||||
del: [i: number],
|
||||
change: [i: number]
|
||||
}>()
|
||||
const props = defineProps<{
|
||||
list: Word[],
|
||||
activeIndex: number,
|
||||
isActive: boolean
|
||||
}>()
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
const listRef: HTMLElement = $ref(null as any)
|
||||
|
||||
function scrollViewToCenter(index: number) {
|
||||
@@ -22,7 +23,7 @@ function scrollViewToCenter(index: number) {
|
||||
}
|
||||
|
||||
watch(() => props.activeIndex, (n: any) => {
|
||||
if (store.sideIsOpen) {
|
||||
if (settingStore.showPanel) {
|
||||
scrollViewToCenter(n)
|
||||
}
|
||||
})
|
||||
@@ -43,19 +44,11 @@ watch(() => props.list, () => {
|
||||
<div class="list" ref="listRef">
|
||||
<TransitionGroup name="list">
|
||||
<template v-for="(item,i) in list" :key="i">
|
||||
<div class="item" @click="$emit('change',i)" :class="activeIndex === i && 'active'">
|
||||
<div class="left">
|
||||
<div class="letter">{{ item.name }}</div>
|
||||
<div class="info">
|
||||
<div class="translate">{{ item.trans.join(';') }}</div>
|
||||
<div class="phonetic">{{ item.usphone }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="audio" @click="playWordAudio(item.name)">播放</div>
|
||||
<Icon icon="fluent:delete-28-regular" width="20" color="#929596"/>
|
||||
</div>
|
||||
</div>
|
||||
<WordItem
|
||||
@click="emit('change',i)"
|
||||
@del="emit('del',i)"
|
||||
:active="activeIndex === i"
|
||||
:word="item"/>
|
||||
</template>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user