Perfect the pop-up box of the selected dictionary
This commit is contained in:
@@ -60,7 +60,7 @@ watch(() => store.load, n => {
|
||||
function getCurrentPractice() {
|
||||
// console.log('store.currentDict',store.currentDict)
|
||||
if (store.isArticle) {
|
||||
// return
|
||||
return
|
||||
let currentArticle = store.currentDict.articles[store.currentDict.chapterIndex]
|
||||
let tempArticle = {...DefaultArticle, ...currentArticle}
|
||||
console.log('article', tempArticle)
|
||||
|
||||
@@ -2,25 +2,28 @@
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {$computed, $ref} from "vue/macros";
|
||||
import {watch} from "vue";
|
||||
import {DictionaryResource} from "@/types.ts";
|
||||
|
||||
const props = defineProps<{
|
||||
category?: string,
|
||||
groupByTag: any[]
|
||||
groupByTag: any,
|
||||
selectDictName: string
|
||||
}>()
|
||||
const emit = defineEmits<{
|
||||
selectDict: [index: DictionaryResource],
|
||||
detail: [],
|
||||
}>()
|
||||
const tagList = $computed(() => Object.keys(props.groupByTag))
|
||||
let currentTag = $ref(tagList[0])
|
||||
let list = $computed(() => {
|
||||
return props.groupByTag[currentTag]
|
||||
})
|
||||
let currentSelectDict = $ref({})
|
||||
let step = $ref(0)
|
||||
|
||||
watch(() => props.groupByTag, () => {
|
||||
currentTag = tagList[0]
|
||||
})
|
||||
|
||||
function selectDict() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -32,16 +35,16 @@ function selectDict() {
|
||||
</div>
|
||||
<div class="dict-list">
|
||||
<div class="dict-item anim"
|
||||
:class="currentSelectDict.name === i.name && 'active'"
|
||||
@click="selectDict(i)"
|
||||
:class="selectDictName === i.name && 'active'"
|
||||
@click="emit('selectDict',i)"
|
||||
v-for="i in list"
|
||||
>
|
||||
<div class="name">{{ i.name }}</div>
|
||||
<div class="desc">{{ i.description }}</div>
|
||||
<div class="num">{{ i.length }}词</div>
|
||||
|
||||
<Icon icon="octicon:arrow-right-24" v-if="currentSelectDict.name === i.name"
|
||||
@click.stop="step = 1"
|
||||
<Icon icon="octicon:arrow-right-24" v-if="selectDictName === i.name"
|
||||
@click.stop="emit('detail')"
|
||||
class="go" width="20" color="#929596"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import {childrenEnglish, dictionaryResources} from '@/assets/dictionary.ts'
|
||||
import {dictionaryResources} from '@/assets/dictionary.ts'
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import {watch} from "vue"
|
||||
import {Dict, Dictionary, DictType, Sort, Word} from "@/types.ts"
|
||||
import {chunk} from "lodash-es";
|
||||
import {onMounted, watch} from "vue"
|
||||
import {Dict, DictionaryResource, DictType, Sort, Word} from "@/types.ts"
|
||||
import {chunk, cloneDeep} from "lodash-es";
|
||||
import {$computed, $ref} from "vue/macros";
|
||||
import WordList from "@/components/WordList.vue";
|
||||
import ChapterList from "@/components/ChapterList.vue"
|
||||
@@ -14,24 +14,34 @@ import codeFlag from '@/assets/img/flags/code.png'
|
||||
import deFlag from '@/assets/img/flags/de.png'
|
||||
import enFlag from '@/assets/img/flags/en.png'
|
||||
import jpFlag from '@/assets/img/flags/ja.png'
|
||||
import bookFlag from '@/assets/img/flags/book.png'
|
||||
import DictGroup from "@/components/Toolbar/DictGroup.vue";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
|
||||
const store = useBaseStore()
|
||||
|
||||
interface IProps {
|
||||
modelValue: boolean,
|
||||
modelValue?: boolean,
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
modelValue: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
])
|
||||
const emit = defineEmits<{
|
||||
close: []
|
||||
}>()
|
||||
|
||||
let currentSelectDict: Dict = $ref(store.currentDict)
|
||||
let step = $ref(0)
|
||||
const options = [
|
||||
{id: 'article', name: '文章', flag: bookFlag},
|
||||
{id: 'en', name: '英语', flag: enFlag},
|
||||
{id: 'ja', name: '日语', flag: jpFlag},
|
||||
{id: 'de', name: '德语', flag: deFlag},
|
||||
{id: 'code', name: 'Code', flag: codeFlag},
|
||||
]
|
||||
let currentLanguage = $ref('en')
|
||||
let currentSelectDict: Dict = $ref(cloneDeep(store.currentDict))
|
||||
let step = $ref(1)
|
||||
|
||||
const currentSelectChapter: Word[] = $computed(() => {
|
||||
return currentSelectDict.chapterWords?.[currentSelectDict.chapterIndex] ?? []
|
||||
@@ -41,25 +51,40 @@ watch(() => props.modelValue, (n: boolean) => {
|
||||
currentSelectDict = store.currentDict
|
||||
})
|
||||
|
||||
async function selectDict(item: Dict) {
|
||||
async function selectDict(item: DictionaryResource) {
|
||||
if (item.name === currentSelectDict.name) return
|
||||
currentSelectDict = {
|
||||
...item,
|
||||
sort: Sort.normal,
|
||||
type: DictType.publicDict,
|
||||
originWords: [],
|
||||
words: [],
|
||||
chapterWordNumber: 15,
|
||||
chapterWordNumber: 30,
|
||||
chapterWords: [],
|
||||
chapterIndex: 0,
|
||||
chapterWordIndex: 0,
|
||||
statistics: []
|
||||
statistics: [],
|
||||
articles: []
|
||||
}
|
||||
let r = await fetch(`/public/${item.url}`)
|
||||
r.json().then(v => {
|
||||
currentSelectDict.originWords = v
|
||||
currentSelectDict.words = v
|
||||
currentSelectDict.chapterWords = chunk(v, currentSelectDict.chapterWordNumber)
|
||||
})
|
||||
if (item.languageCategory === 'article') {
|
||||
currentSelectDict.type = DictType.publicArticle
|
||||
let r = await fetch(`${item.url}`)
|
||||
r.json().then(v => {
|
||||
currentSelectDict.articles = cloneDeep(v.map(v => {
|
||||
v.id = uuidv4()
|
||||
return v
|
||||
}))
|
||||
})
|
||||
} else {
|
||||
currentSelectDict.type = DictType.publicDict
|
||||
let r = await fetch(`${item.url}`)
|
||||
r.json().then(v => {
|
||||
currentSelectDict.originWords = v
|
||||
currentSelectDict.words = v
|
||||
currentSelectDict.chapterWords = chunk(v, currentSelectDict.chapterWordNumber)
|
||||
})
|
||||
}
|
||||
step = 1
|
||||
}
|
||||
|
||||
function changeDict() {
|
||||
@@ -68,7 +93,6 @@ function changeDict() {
|
||||
}
|
||||
|
||||
function close() {
|
||||
console.log('close')
|
||||
emit('close')
|
||||
}
|
||||
|
||||
@@ -76,14 +100,6 @@ function resetChapterList() {
|
||||
currentSelectDict.chapterWords = chunk(currentSelectDict.words, currentSelectDict.chapterWordNumber)
|
||||
}
|
||||
|
||||
const options = [
|
||||
{id: 'en', name: '英语', flag: enFlag},
|
||||
{id: 'ja', name: '日语', flag: jpFlag},
|
||||
{id: 'de', name: '德语', flag: deFlag},
|
||||
{id: 'code', name: 'Code', flag: codeFlag},
|
||||
]
|
||||
let currentLanguage = $ref('en')
|
||||
|
||||
function groupBy<T>(elements: T[], iteratee: (value: T) => string) {
|
||||
return elements.reduce<Record<string, T[]>>((result, value) => {
|
||||
const key = iteratee(value)
|
||||
@@ -96,8 +112,8 @@ function groupBy<T>(elements: T[], iteratee: (value: T) => string) {
|
||||
}, {})
|
||||
}
|
||||
|
||||
function groupByDictTags(dicts: Dictionary[]) {
|
||||
return dicts.reduce<Record<string, Dictionary[]>>((result, dict) => {
|
||||
function groupByDictTags(dicts: DictionaryResource[]) {
|
||||
return dicts.reduce<Record<string, DictionaryResource[]>>((result, dict) => {
|
||||
dict.tags.forEach((tag) => {
|
||||
if (Object.prototype.hasOwnProperty.call(result, tag)) {
|
||||
result[tag].push(dict)
|
||||
@@ -113,16 +129,18 @@ const groupedByCategoryAndTag = $computed(() => {
|
||||
const currentLanguageCategoryDicts = dictionaryResources.filter((dict) => dict.languageCategory === currentLanguage)
|
||||
const groupedByCategory = Object.entries(groupBy(currentLanguageCategoryDicts, (dict) => dict.category))
|
||||
const groupedByCategoryAndTag = groupedByCategory.map(
|
||||
([category, dicts]) => [category, groupByDictTags(dicts)] as [string, Record<string, Dictionary[]>],
|
||||
([category, dicts]) => [category, groupByDictTags(dicts)] as [string, Record<string, DictionaryResource[]>],
|
||||
)
|
||||
console.log('groupedByCategoryAndTag', groupedByCategoryAndTag)
|
||||
return groupedByCategoryAndTag
|
||||
})
|
||||
|
||||
let radio1 = $ref('')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :show-close="false"
|
||||
:header="false"
|
||||
@close="close">
|
||||
<div class="slide">
|
||||
<div class="slide-list" :class="`step${step}`">
|
||||
@@ -146,9 +164,12 @@ const groupedByCategoryAndTag = $computed(() => {
|
||||
<div class="dict-list-wrapper">
|
||||
<DictGroup
|
||||
v-for="item in groupedByCategoryAndTag"
|
||||
:select-dict-name="currentSelectDict.name"
|
||||
@selectDict="selectDict"
|
||||
@detail="step = 1"
|
||||
:groupByTag="item[1]"/>
|
||||
</div>
|
||||
<div class="chapter-wrapper">
|
||||
<div class="chapter-wrapper" v-if="false">
|
||||
<div class="chapter-word-number">
|
||||
<span>每章单词数:</span>
|
||||
<el-slider :min="10"
|
||||
@@ -175,7 +196,7 @@ const groupedByCategoryAndTag = $computed(() => {
|
||||
<div class="left">
|
||||
<Icon icon="octicon:arrow-left-24"
|
||||
@click.stop="step = 0"
|
||||
class="go" width="20" color="#ffffff"/>
|
||||
class="go" width="20" color="#000000"/>
|
||||
<div class="title">
|
||||
词典详情
|
||||
</div>
|
||||
@@ -187,24 +208,95 @@ const groupedByCategoryAndTag = $computed(() => {
|
||||
</header>
|
||||
<div class="page-content">
|
||||
<div class="dict-info">
|
||||
<div class="dict-item">
|
||||
<div class="detail">
|
||||
<div class="name">{{ currentSelectDict.name }}</div>
|
||||
<div class="desc">{{ currentSelectDict.description }}</div>
|
||||
<div class="num">{{ currentSelectDict.length }}词</div>
|
||||
<div class="num">{{ currentSelectDict.chapterWords.length }}章</div>
|
||||
</div>
|
||||
<div class="chapter-word-number">
|
||||
<span>每章单词数:</span>
|
||||
<el-slider :min="10"
|
||||
:step="10"
|
||||
:max="100"
|
||||
v-model="currentSelectDict.chapterWordNumber"
|
||||
@change="resetChapterList"
|
||||
/>
|
||||
<span>{{ currentSelectDict.chapterWordNumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chapter-wrapper">
|
||||
<ChapterList :list="currentSelectDict.chapterWords"
|
||||
v-model:active-index="currentSelectDict.chapterIndex"
|
||||
/>
|
||||
</div>
|
||||
<div class="other">
|
||||
<WordList class="word-list" :list="currentSelectChapter" :activeIndex="-1" :isActive="false"/>
|
||||
<WordList
|
||||
v-if="false"
|
||||
class="word-list" :list="[]" :activeIndex="-1" :isActive="false"/>
|
||||
<!-- class="word-list" :list="currentSelectDict.words" :activeIndex="-1" :isActive="false"/>-->
|
||||
<div class="footer">
|
||||
<BaseButton>返回</BaseButton>
|
||||
<BaseButton @click="step = 0">返回</BaseButton>
|
||||
<BaseButton>确定</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="title">学习设置</div>
|
||||
<div class="row">
|
||||
<div class="label">学习模式</div>
|
||||
<div class="option">
|
||||
<el-radio-group v-model="radio1" class="ml-4">
|
||||
<el-radio label="1" size="large">再认</el-radio>
|
||||
<el-radio label="2" size="large">拼写</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">单词发音</div>
|
||||
<div class="option">
|
||||
<el-radio-group v-model="radio1" class="ml-4">
|
||||
<el-radio label="1" size="large">美音</el-radio>
|
||||
<el-radio label="2" size="large">英音</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">词序</div>
|
||||
<div class="option">
|
||||
<el-radio-group v-model="radio1" class="ml-4">
|
||||
<el-radio label="1" size="large">随机</el-radio>
|
||||
<el-radio label="2" size="large">正常</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">单词自动发音</div>
|
||||
<div class="option">
|
||||
<el-switch v-model="radio1"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">是否显示翻译</div>
|
||||
<div class="option">
|
||||
<el-switch v-model="radio1"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="label">忽略大小写</div>
|
||||
<div class="option">
|
||||
<el-switch v-model="radio1"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -334,11 +426,13 @@ $footer-height: 40rem;
|
||||
height: $header-height;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #000;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
gap: 10rem;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,22 +440,63 @@ $footer-height: 40rem;
|
||||
display: flex;
|
||||
height: calc(100% - $header-height);
|
||||
position: relative;
|
||||
gap: $space;
|
||||
|
||||
.dict-info {
|
||||
width: 20%;
|
||||
flex: 3;
|
||||
color: black;
|
||||
|
||||
.detail {
|
||||
cursor: pointer;
|
||||
padding: 10rem;
|
||||
min-height: 100rem;
|
||||
position: relative;
|
||||
border-radius: 10rem;
|
||||
background: var(--color-item-bg);
|
||||
color: var(--color-font-1);
|
||||
font-size: 14rem;
|
||||
|
||||
.name {
|
||||
font-size: 28rem;
|
||||
margin-bottom: 10rem;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 18rem;
|
||||
margin-bottom: 30rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chapter-wrapper {
|
||||
width: 40%;
|
||||
.setting {
|
||||
flex: 5;
|
||||
background: white;
|
||||
border-radius: 10rem;
|
||||
background: var(--color-item-bg);
|
||||
color: var(--color-font-1);
|
||||
padding: 10rem;
|
||||
|
||||
.chapter-list {
|
||||
height: 100%;
|
||||
.title {
|
||||
font-size: 20rem;
|
||||
color: gray;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40rem;
|
||||
}
|
||||
}
|
||||
|
||||
.other {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
flex: 5;
|
||||
background: white;
|
||||
border-radius: 10rem;
|
||||
background: var(--color-item-bg);
|
||||
color: var(--color-font-1);
|
||||
padding: 10rem;
|
||||
|
||||
.word-list {
|
||||
height: calc(100% - $footer-height);
|
||||
|
||||
@@ -81,7 +81,7 @@ watch(() => settingStore.showToolbar, n => {
|
||||
|
||||
<Tooltip title="切换主题">
|
||||
<IconWrapper>
|
||||
<Icon icon="ep:moon" v-if="store.theme === 'dark'"
|
||||
<Icon icon="ep:moon" v-if="settingStore.theme === 'dark'"
|
||||
@click="toggle"/>
|
||||
<Icon icon="tabler:sun" v-else @click="toggle"/>
|
||||
</IconWrapper>
|
||||
|
||||
Reference in New Issue
Block a user