Perfect the pop-up box of the selected dictionary

This commit is contained in:
zyronon
2023-09-30 20:16:24 +08:00
parent af6b41d682
commit 87467c1f2a
8 changed files with 2056 additions and 1986 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

View File

@@ -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)

View File

@@ -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>

View File

@@ -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);

View File

@@ -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>

View File

@@ -31,7 +31,7 @@ export const useBaseStore = defineStore('base', {
originWords: [],
articles: [],
words: [],
chapterWordNumber: 15,
chapterWordNumber: 30,
chapterWords: [],
chapterIndex: 0,
chapterWordIndex: 0,
@@ -45,7 +45,7 @@ export const useBaseStore = defineStore('base', {
originWords: [],
articles: [],
words: [],
chapterWordNumber: 15,
chapterWordNumber: 30,
chapterWords: [],
chapterIndex: 0,
chapterWordIndex: 0,
@@ -59,7 +59,7 @@ export const useBaseStore = defineStore('base', {
originWords: [],
articles: [],
words: [],
chapterWordNumber: 15,
chapterWordNumber: 30,
chapterWords: [],
chapterIndex: 0,
chapterWordIndex: 0,
@@ -81,13 +81,13 @@ export const useBaseStore = defineStore('base', {
// url: '/dicts/NCE_2.json',
// },
dict: {
name: '新概念英语-2',
name: '新概念英语2-课文',
sort: Sort.normal,
type: DictType.publicArticle,
originWords: [],
articles: [],
words: [],
chapterWordNumber: 15,
chapterWordNumber: 30,
chapterWords: [],
chapterIndex: 0,
chapterWordIndex: 0,
@@ -96,13 +96,13 @@ export const useBaseStore = defineStore('base', {
},
myDicts: [
{
name: '新概念英语-2',
name: '新概念英语2-课文',
sort: Sort.normal,
type: DictType.publicArticle,
originWords: [],
articles: [],
words: [],
chapterWordNumber: 15,
chapterWordNumber: 30,
chapterWords: [],
chapterIndex: 0,
chapterWordIndex: 0,

View File

@@ -1,5 +1,3 @@
import {v4 as uuidv4} from 'uuid';
export type Word = {
"name": string,
"usphone": string,
@@ -19,10 +17,8 @@ export const SaveConfigKey = 'typing-word-config'
export const PronunciationApi = 'https://dict.youdao.com/dictvoice?audio='
export type PronunciationType = 'us' | 'uk' | 'romaji' | 'zh' | 'ja' | 'de'
export type PhoneticType = 'us' | 'uk' | 'romaji' | 'zh' | 'ja' | 'de'
export type LanguageType = 'en' | 'romaji' | 'zh' | 'ja' | 'code' | 'de'
export type LanguageCategoryType = 'en' | 'ja' | 'de' | 'code'
export type LanguageCategoryType = 'en' | 'ja' | 'de' | 'code' | 'article'
export type DictionaryResource = {
@@ -35,54 +31,21 @@ export type DictionaryResource = {
length: number
language: LanguageType
languageCategory: LanguageCategoryType
//override default pronunciation when not undefined
defaultPronIndex?: number
}
export type Dictionary = {
id: string
name: string
description: string
category: string
tags: string[]
url: string
length: number
language: LanguageType
languageCategory: LanguageCategoryType
// calculated in the store
chapterCount: number
//override default pronunciation when not undefined
defaultPronIndex?: number
}
export type PronunciationConfig = {
name: string
pron: PronunciationType
}
export type LanguagePronunciationMapConfig = {
defaultPronIndex: number
pronunciation: PronunciationConfig[]
}
export type LanguagePronunciationMap = {
[key in LanguageType]: LanguagePronunciationMapConfig
}
export type SoundResource = {
key: string
name: string
filename: string
}
export interface DictJson {
description: string,
category: string,
tags: string[],
export interface Dict {
name: string,
sort: Sort,
type: DictType,
originWords: Word[],//原始单词
words: Word[],
chapterWordNumber: number,//章节单词数量
chapterWords: Word[][],
articles: Article[],
chapterIndex: number,
chapterWordIndex: number,
statistics: Statistics[],
url: string,
length: number,
language: string,
languageCategory: string,
}
export enum DictType {
@@ -154,21 +117,6 @@ export const DefaultArticle: Article = {
useTranslateType: TranslateType.network
}
export interface Dict {
name: string,
sort: Sort,
type: DictType,
originWords: Word[],//原始单词
words: Word[],
chapterWordNumber: number,//章节单词数量
chapterWords: Word[][],
articles: Article[],
chapterIndex: number,
chapterWordIndex: number,
statistics: Statistics[],
url: string,
}
export interface Statistics {
startDate: number,//开始日期
endDate: number//结束日期
@@ -198,7 +146,6 @@ export enum Sort {
reverse = 2
}
export const ShortKeyMap = {
Show: 'Escape',
Ignore: 'Tab',