Perfect the pop-up box of the selected dictionary

This commit is contained in:
zyronon
2023-09-29 15:16:32 +08:00
parent 24eced7ed7
commit af6b41d682
13 changed files with 869 additions and 657 deletions

1
auto-imports.d.ts vendored
View File

@@ -6,5 +6,4 @@
export {}
declare global {
const ElMessage: typeof import('element-plus/es')['ElMessage']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
}

1
components.d.ts vendored
View File

@@ -17,6 +17,7 @@ declare module 'vue' {
ChapterDetail: typeof import('./src/components/ChapterDetail.vue')['default']
ChapterList: typeof import('./src/components/ChapterList.vue')['default']
Close: typeof import('./src/components/Close.vue')['default']
DictGroup: typeof import('./src/components/Toolbar/DictGroup.vue')['default']
DictList: typeof import('./src/components/DictList.vue')['default']
DictModal: typeof import('./src/components/Toolbar/DictModal.vue')['default']
EditAbleText: typeof import('./src/components/EditAbleText.vue')['default']

1213
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -51,10 +51,10 @@ useEventListener('keyup', (e: KeyboardEvent) => {
<template>
<!-- <Backgorund/>-->
<div class="main-page">
<!-- <Practice/>-->
<Practice/>
<!-- <AddArticle/>-->
<!-- <Side/>-->
<BatchAddArticle/>
<!-- <BatchAddArticle/>-->
</div>
</template>

View File

@@ -1876,6 +1876,7 @@ export const dictionaryResources: DictionaryResource[] = [
// language: 'ja',
// },
]
//
// export const dictionaries: Dictionary[] = dictionaryResources.map((resource) => ({
// ...resource,

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/assets/img/flags/de.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/assets/img/flags/en.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/assets/img/flags/ja.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -506,8 +506,10 @@ function exportData() {
</div>
<div class="options" v-if="article.text.trim()">
<div class="warning">
<Icon icon="typcn:warning-outline"/>
共有{{ failCount }}句没有翻译
<template v-if="failCount">
<Icon icon="typcn:warning-outline"/>
共有{{ failCount }}句没有翻译
</template>
</div>
<div class="left">
<BaseButton @click="save('save')">保存</BaseButton>
@@ -683,7 +685,7 @@ function exportData() {
align-items: center;
font-size: 20rem;
color: red;
gap: $space;
gap: 10rem;
}

View File

@@ -171,24 +171,23 @@ function test() {
})
}
</script>
<template>
<div class="practice">
<Toolbar/>
<!-- <BaseButton @click="test">test</BaseButton>-->
<TypeArticle
v-if="store.isArticle"
:article="articleData.article"
:sectionIndex="articleData.sectionIndex"
:sentenceIndex="articleData.sentenceIndex"
:wordIndex="articleData.wordIndex"
:stringIndex="articleData.stringIndex"
/>
<TypeWord
:words="wordData.words"
:index="wordData.index"
v-else/>
<!-- <TypeArticle-->
<!-- v-if="store.isArticle"-->
<!-- :article="articleData.article"-->
<!-- :sectionIndex="articleData.sectionIndex"-->
<!-- :sentenceIndex="articleData.sentenceIndex"-->
<!-- :wordIndex="articleData.wordIndex"-->
<!-- :stringIndex="articleData.stringIndex"-->
<!-- />-->
<!-- <TypeWord-->
<!-- :words="wordData.words"-->
<!-- :index="wordData.index"-->
<!-- v-else/>-->
<Footer/>
</div>
<Statistics

View File

@@ -0,0 +1,113 @@
<script setup lang="ts">
import {Icon} from "@iconify/vue";
import {$computed, $ref} from "vue/macros";
import {watch} from "vue";
const props = defineProps<{
category?: string,
groupByTag: any[]
}>()
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>
<div class="tags">
<div class="tag" :class="i === currentTag &&'active'"
@click="currentTag = i"
v-for="i in Object.keys(groupByTag)">{{ i }}
</div>
</div>
<div class="dict-list">
<div class="dict-item anim"
:class="currentSelectDict.name === i.name && 'active'"
@click="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"
class="go" width="20" color="#929596"/>
</div>
</div>
</template>
<style scoped lang="scss">
.tags {
display: flex;
flex-wrap: wrap;
margin: 10rem 0;
.tag {
color: var(--color-font-1);
cursor: pointer;
padding: 5rem 10rem;
border-radius: 20rem;
&.active {
color: var(--color-font-active-1);
background: gray;
}
}
}
.dict-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15rem;
.dict-item {
cursor: pointer;
padding: 10rem;
min-height: 100rem;
border-radius: 10rem;
position: relative;
background: var(--color-item-bg);
color: var(--color-font-1);
font-size: 14rem;
.name {
font-size: 18rem;
}
.desc {
color: var(--color-font-2);
}
.num {
font-weight: bold;
}
.go {
position: absolute;
right: 10rem;
bottom: 15rem;
}
&.active {
background: var(--color-item-active);
color: var(--color-font-active-1);
.desc {
color: var(--color-font-active-2);
}
}
}
}
</style>

View File

@@ -1,8 +1,8 @@
<script setup lang="ts">
import {childrenEnglish} from '@/assets/dictionary.ts'
import {childrenEnglish, dictionaryResources} from '@/assets/dictionary.ts'
import {useBaseStore} from "@/stores/base.ts"
import {watch} from "vue"
import {Dict, DictType, Sort, Word} from "@/types.ts"
import {Dict, Dictionary, DictType, Sort, Word} from "@/types.ts"
import {chunk} from "lodash-es";
import {$computed, $ref} from "vue/macros";
import WordList from "@/components/WordList.vue";
@@ -10,6 +10,11 @@ import ChapterList from "@/components/ChapterList.vue"
import Modal from "@/components/Modal/Modal.vue";
import BaseButton from "@/components/BaseButton.vue";
import {Icon} from '@iconify/vue';
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 DictGroup from "@/components/Toolbar/DictGroup.vue";
const store = useBaseStore()
@@ -70,6 +75,50 @@ function close() {
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)
if (Object.prototype.hasOwnProperty.call(result, key)) {
result[key].push(value)
} else {
result[key] = [value]
}
return result
}, {})
}
function groupByDictTags(dicts: Dictionary[]) {
return dicts.reduce<Record<string, Dictionary[]>>((result, dict) => {
dict.tags.forEach((tag) => {
if (Object.prototype.hasOwnProperty.call(result, tag)) {
result[tag].push(dict)
} else {
result[tag] = [dict]
}
})
return result
}, {})
}
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[]>],
)
console.log('groupedByCategoryAndTag', groupedByCategoryAndTag)
return groupedByCategoryAndTag
})
</script>
<template>
@@ -80,14 +129,12 @@ function resetChapterList() {
<div class="dict-page">
<header>
<div class="tabs">
<div class="tab">
<span>英语</span>
</div>
<div class="tab">
<span>日语</span>
</div>
<div class="tab">
<span>德语</span>
<div class="tab"
:class="currentLanguage === item.id && 'active'"
@click="currentLanguage = item.id"
v-for="item in options">
<img :src='item.flag'/>
<span>{{ item.name }}</span>
</div>
</div>
<Icon @click="close"
@@ -97,23 +144,9 @@ function resetChapterList() {
</header>
<div class="page-content">
<div class="dict-list-wrapper">
<div class="tags">
<div class="tag" :class="i === 5 &&'active'" v-for="i in 2">六级</div>
</div>
<div class="dict-list">
<div class="dict-item anim"
:class="currentSelectDict.name === i.name && 'active'" v-for="i in childrenEnglish"
@click="selectDict(i)"
>
<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"
class="go" width="20" color="#929596"/>
</div>
</div>
<DictGroup
v-for="item in groupedByCategoryAndTag"
:groupByTag="item[1]"/>
</div>
<div class="chapter-wrapper">
<div class="chapter-word-number">
@@ -203,42 +236,6 @@ $header-height: 60rem;
}
}
.dict-item {
cursor: pointer;
padding: 10rem;
border-radius: 10rem;
position: relative;
background: var(--color-item-bg);
color: var(--color-font-1);
font-size: 14rem;
.name {
font-size: 18rem;
}
.desc {
color: var(--color-font-2);
}
.num {
font-weight: bold;
}
.go {
position: absolute;
right: 10rem;
bottom: 15rem;
}
&.active {
background: var(--color-item-active);
color: var(--color-font-active-1);
.desc {
color: var(--color-font-active-2);
}
}
}
$footer-height: 40rem;
@@ -292,7 +289,19 @@ $footer-height: 40rem;
cursor: pointer;
padding: 10rem;
padding-bottom: 5rem;
border-bottom: 2px solid $main;
transition: all .5s;
border-bottom: 2px solid transparent;
display: flex;
align-items: center;
gap: 6rem;
&.active {
border-bottom: 2px solid $main;
}
img {
height: 30rem;
}
}
}
}
@@ -307,29 +316,6 @@ $footer-height: 40rem;
height: 100%;
padding-right: $space;
.tags {
display: flex;
flex-wrap: wrap;
margin-bottom: 10rem;
.tag {
color: var(--color-font-1);
cursor: pointer;
padding: 5rem 10rem;
border-radius: 20rem;
&.active {
color: var(--color-font-active-1);
background: gray;
}
}
}
.dict-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15rem;
}
}
}
}