Perfect the pop-up box of the selected dictionary
This commit is contained in:
1
auto-imports.d.ts
vendored
1
auto-imports.d.ts
vendored
@@ -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
1
components.d.ts
vendored
@@ -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
1213
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -51,10 +51,10 @@ useEventListener('keyup', (e: KeyboardEvent) => {
|
||||
<template>
|
||||
<!-- <Backgorund/>-->
|
||||
<div class="main-page">
|
||||
<!-- <Practice/>-->
|
||||
<Practice/>
|
||||
<!-- <AddArticle/>-->
|
||||
<!-- <Side/>-->
|
||||
<BatchAddArticle/>
|
||||
<!-- <BatchAddArticle/>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1876,6 +1876,7 @@ export const dictionaryResources: DictionaryResource[] = [
|
||||
// language: 'ja',
|
||||
// },
|
||||
]
|
||||
|
||||
//
|
||||
// export const dictionaries: Dictionary[] = dictionaryResources.map((resource) => ({
|
||||
// ...resource,
|
||||
|
||||
BIN
src/assets/img/flags/code.png
Normal file
BIN
src/assets/img/flags/code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/img/flags/de.png
Normal file
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
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
BIN
src/assets/img/flags/ja.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
113
src/components/Toolbar/DictGroup.vue
Normal file
113
src/components/Toolbar/DictGroup.vue
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user