Merge branch 'dev'

This commit is contained in:
zyronon
2023-11-03 16:50:10 +08:00
14 changed files with 255 additions and 51 deletions

View File

@@ -12,7 +12,7 @@ import {onMounted} from "vue"
const canvas = $ref<HTMLCanvasElement>()
onMounted(() => {
console.log('canvas;', canvas)
// console.log('canvas;', canvas)
let ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

View File

@@ -24,17 +24,11 @@ const list: any[] = $computed(() => {
function showWordListModal(index: number, item: Word[]) {
if (runtimeStore.editDict.translateLanguage === 'common') {
console.time()
item.map((w: Word) => {
if (!w.trans.length) {
let res = runtimeStore.translateWordList.find(a => a.name === w.name)
if (res) w = Object.assign(w, res)
}
})
console.timeEnd()
}
emitter.emit(EventKey.openWordListModal, {title: `${index + 1}`, list: item})
emitter.emit(EventKey.openWordListModal, {
title: `${index + 1}`,
translateLanguage: runtimeStore.editDict.translateLanguage,
list: item
})
}
</script>

View File

@@ -18,10 +18,8 @@ let wordData = $ref({
watch([
() => store.load,
() => store.current.index,
() => store.current.dictType,
() => store.currentDict.chapterIndex,
() => store.currentDict.chapterWordNumber,
() => store.currentDict.words,
], n => {
getCurrentPractice()
})
@@ -36,7 +34,7 @@ function getCurrentPractice() {
}
wordData.words = cloneDeep(store.chapter)
wordData.index = 0
console.log('wordData', wordData)
// console.log('wordData', wordData)
}
onMounted(() => {

View File

@@ -237,6 +237,8 @@ useOnKeyboardEventListener(onKeyDown, onKeyUp)
class="word-list"
:is-active="active"
@change="(i:number) => data.index = i"
:show-word="!settingStore.dictation"
:show-translate="settingStore.translate"
:list="data.words"
:activeIndex="data.index"/>
</div>

View File

@@ -1,9 +1,9 @@
<script setup lang="ts">
import {dictionaryResources} from '@/assets/dictionary.ts'
import {useBaseStore} from "@/stores/base.ts"
import {watch} from "vue"
import {DefaultDict, Dict, DictResource, DictType, languageCategoryOptions} from "@/types.ts"
import {chunk, cloneDeep, groupBy} from "lodash-es";
import {onUnmounted, watch} from "vue"
import {DefaultDict, Dict, DictResource, DictType, languageCategoryOptions, Sort} from "@/types.ts"
import {chunk, cloneDeep, groupBy, reverse, shuffle} from "lodash-es";
import {$computed, $ref} from "vue/macros";
import Modal from "@/components/Modal/Modal.vue";
import BaseButton from "@/components/BaseButton.vue";
@@ -17,6 +17,7 @@ import WordListModal from "@/components/WordListModal.vue";
import {isArticle} from "@/hooks/article.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {useSettingStore} from "@/stores/setting.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts";
interface IProps {
modelValue?: boolean,
@@ -98,9 +99,6 @@ function close() {
emit('close')
}
function resetChapterList() {
runtimeStore.editDict.chapterWords = chunk(runtimeStore.editDict.words, runtimeStore.editDict.chapterWordNumber)
}
function groupByDictTags(dictList: DictResource[]) {
return dictList.reduce<Record<string, DictResource[]>>((result, dict) => {
@@ -148,6 +146,32 @@ const dictIsArticle = $computed(() => {
return isArticle(runtimeStore.editDict.type)
})
function showAllWordModal() {
emitter.emit(EventKey.openWordListModal, {
title: runtimeStore.editDict.name,
translateLanguage: runtimeStore.editDict.translateLanguage,
list: runtimeStore.editDict.words
})
}
function resetChapterList() {
runtimeStore.editDict.chapterWords = chunk(runtimeStore.editDict.words, runtimeStore.editDict.chapterWordNumber)
}
function changeSort(v) {
if (v === Sort.normal) {
runtimeStore.editDict.words = cloneDeep(runtimeStore.editDict.originWords)
} else if (v === Sort.random) {
runtimeStore.editDict.words = shuffle(cloneDeep(runtimeStore.editDict.originWords))
} else {
runtimeStore.editDict.words = reverse(cloneDeep(runtimeStore.editDict.originWords))
}
resetChapterList()
}
onUnmounted(() => {
close()
})
</script>
<template>
@@ -215,7 +239,9 @@ const dictIsArticle = $computed(() => {
>总文章{{ runtimeStore.editDict.articles.length }}
</div>
<div class="num" v-else>
总词汇<span>{{ runtimeStore.editDict.originWords.length }}</span>
总词汇<span class="count"
@click="showAllWordModal"
>{{ runtimeStore.editDict.originWords.length }}</span>
</div>
<div class="num">开始日期-</div>
<div class="num">花费时间-</div>
@@ -240,10 +266,22 @@ const dictIsArticle = $computed(() => {
<span>{{ runtimeStore.editDict.chapterWordNumber }}</span>
</div>
</div>
<div class="row">
<div class="label">单词顺序</div>
<div class="option">
<el-radio-group v-model="runtimeStore.editDict.sort"
@change="changeSort"
>
<el-radio :label="Sort.normal" size="large">默认</el-radio>
<el-radio :label="Sort.random" size="large">随机</el-radio>
<el-radio :label="Sort.reverse" size="large">反转</el-radio>
</el-radio-group>
</div>
</div>
<div class="row">
<div class="label">学习模式</div>
<div class="option">
<el-radio-group v-model="settingStore.dictation" class="ml-4">
<el-radio-group v-model="settingStore.dictation">
<el-radio :label="false" size="large">再认</el-radio>
<el-radio :label="true" size="large">拼写</el-radio>
</el-radio-group>
@@ -252,21 +290,12 @@ const dictIsArticle = $computed(() => {
<div class="row">
<div class="label">单词发音</div>
<div class="option">
<el-radio-group v-model="settingStore.wordSoundType" class="ml-4">
<el-radio-group v-model="settingStore.wordSoundType">
<el-radio label="us" size="large">美音</el-radio>
<el-radio label="uk" 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">
@@ -514,6 +543,10 @@ $header-height: 60rem;
height: 40rem;
word-break: keep-all;
gap: 10rem;
.el-radio {
margin-right: 10rem;
}
}
}

View File

@@ -114,7 +114,7 @@ watch(() => store.load, n => {
</Tooltip>
</div>
<div class="with-bg">
<div class="with-bg anim">
<Tooltip title="设置">
<IconWrapper>
<Icon icon="uil:setting" @click="showSettingModal = true"/>

View File

@@ -13,10 +13,14 @@ const props = withDefaults(defineProps<{
activeIndex?: number,
showDel?: boolean,
isActive?: boolean
showTranslate?: boolean
showWord?: boolean
}>(), {
activeIndex: -1,
isActive: false,
showDel: false
showDel: false,
showTranslate: true,
showWord: true
})
const emit = defineEmits<{
@@ -77,11 +81,11 @@ const {
@del="delWrongWord(word)"
>
<div class="item-title">
<span class="word" :class="settingStore.dictation && 'text-shadow'">{{ word.name }}</span>
<span class="word" :class="!showWord && 'text-shadow'">{{ word.name }}</span>
<span class="phonetic">{{ word.usphone }}</span>
<VolumeIcon class="volume" @click="playWordAudio(word.name)"></VolumeIcon>
</div>
<div class="item-sub-title" v-if="word.trans.length && settingStore.translate">
<div class="item-sub-title" v-if="word.trans.length && showTranslate">
<div v-for="item in word.trans">{{ item }}</div>
</div>
</ListItem>

View File

@@ -1,30 +1,69 @@
<script setup lang="ts">
import VolumeIcon from "@/components/VolumeIcon.vue";
import {Icon} from "@iconify/vue";
import Modal from "@/components/Modal/Modal.vue";
import {$ref} from "vue/macros";
import {onMounted, onUnmounted} from "vue";
import {onMounted, onUnmounted, watch} from "vue";
import {usePlayWordAudio} from "@/hooks/sound.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import ListItem from "@/components/ListItem.vue";
import {Word} from "@/types.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
let show = $ref(false)
let loading = $ref(false)
let list = $ref([])
let title = $ref('')
let progress = $ref(0)
const playWordAudio = usePlayWordAudio()
const runtimeStore = useRuntimeStore()
onMounted(() => {
emitter.on(EventKey.openWordListModal, (val: any) => {
show = true
list = val.list
title = val.title
show = true
let count = 0
if (val.translateLanguage === 'common') {
for (let index = 0; index < list.length; index++) {
let w = list[index]
if (!w.trans.length) {
requestIdleCallback(() => {
if (list.length) {
let res = runtimeStore.translateWordList.find(a => a.name === w.name)
if (res) w = Object.assign(w, res)
count++
if (count === list.length) {
progress = 100
} else {
if (count % 30 === 0) progress = (count / list.length) * 100
}
}
})
} else {
count++
if (count === list.length) {
progress = 100
} else {
if (count % 30 === 0) progress = (count / list.length) * 100
}
}
}
}
})
})
watch(() => show, v => {
if (!v) {
list = []
progress = 0
}
})
onUnmounted(() => {
emitter.off(EventKey.openWordListModal)
})
</script>
<template>
@@ -32,6 +71,14 @@ onUnmounted(() => {
:title="title"
v-model="show">
<div class="all-word">
<div class="progress-wrapper" v-if="progress !== 100 && list.length > 1000">
<span>词典加载进度:</span>
<el-progress :percentage="progress"
:stroke-width="8"
:duration="0"
:indeterminate="false"
:show-text="false"/>
</div>
<virtual-list class="virtual-list"
:keeps="20"
data-key="name"
@@ -64,6 +111,19 @@ onUnmounted(() => {
padding-top: 0;
width: 400rem;
height: 75vh;
.progress-wrapper {
height: 45rem;
display: flex;
align-items: center;
gap: 10rem;
font-size: 14rem;
color: var(--color-font-1);
.el-progress {
flex: 1;
}
}
}
</style>

View File

@@ -0,0 +1,104 @@
<script setup lang="ts">
import VolumeIcon from "@/components/VolumeIcon.vue";
import Modal from "@/components/Modal/Modal.vue";
import {$ref} from "vue/macros";
import {onMounted, onUnmounted} from "vue";
import {usePlayWordAudio} from "@/hooks/sound.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import ListItem from "@/components/ListItem.vue";
import {Word} from "@/types.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {cloneDeep} from "lodash-es";
let show = $ref(false)
let loading = $ref(false)
let list = $ref([])
let title = $ref('')
const playWordAudio = usePlayWordAudio()
const runtimeStore = useRuntimeStore()
onMounted(() => {
emitter.on(EventKey.openWordListModal, (val: any) => {
loading = true
show = true
list = cloneDeep(val.list)
title = val.title
setTimeout(() => {
if (val.translateLanguage === 'common') {
console.time()
let tempList = cloneDeep(val.list)
tempList.map((w: Word) => {
if (!w.trans.length) {
let res = runtimeStore.translateWordList.find(a => a.name === w.name)
if (res) w = Object.assign(w, res)
}
})
list = cloneDeep(tempList)
console.timeEnd()
}
// loading = false
}, 500)
})
})
onUnmounted(() => {
emitter.off(EventKey.openWordListModal)
})
</script>
<template>
<Modal
:title="title"
v-model="show">
<div class="all-word">
<virtual-list class="virtual-list"
:keeps="20"
data-key="name"
v-loading="loading"
:data-sources="list"
:estimate-size="85"
item-class="dict-virtual-item"
>
<template #={source}>
<ListItem
class="common-list-item"
:show-volume="true">
<div class="item-title">
<span class="word">{{ source.name }}</span>
<span class="phonetic">{{ source.usphone }}</span>
<VolumeIcon class="volume" @click="playWordAudio(source.name)"></VolumeIcon>
</div>
<div class="item-sub-title" v-if="source.trans.length">{{ source.trans.join('') }}</div>
</ListItem>
</template>
</virtual-list>
</div>
</Modal>
</template>
<style lang="scss" scoped>
@import "@/assets/css/style";
.all-word {
padding: $space;
padding-top: 0;
width: 400rem;
height: 75vh;
}
</style>
<style lang="scss">
@import "@/assets/css/variable.scss";
.virtual-list {
overflow: auto;
height: 100%;
}
.dict-virtual-item {
margin-bottom: 15rem;
}
</style>