save
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -44,6 +44,7 @@ declare module 'vue' {
|
||||
List: typeof import('./src/components/List.vue')['default']
|
||||
MiniModal: typeof import('./src/components/MiniModal.vue')['default']
|
||||
Modal: typeof import('./src/components/Modal/Modal.vue')['default']
|
||||
Options: typeof import('./src/components/Practice/Options.vue')['default']
|
||||
PopConfirm: typeof import('./src/components/PopConfirm.vue')['default']
|
||||
Practice: typeof import('./src/components/Practice/Practice.vue')['default']
|
||||
PracticeArticle: typeof import('./src/components/Practice/PracticeArticle/PracticeArticle.vue')['default']
|
||||
|
||||
51
src/components/Practice/Options.vue
Normal file
51
src/components/Practice/Options.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
|
||||
const emit = defineEmits<{
|
||||
remove: [],
|
||||
collect: [],
|
||||
skip: [],
|
||||
edit: [],
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="options">
|
||||
<Tooltip title="编辑(快捷键:Ctrl + E)">
|
||||
<IconWrapper>
|
||||
<Icon icon="tabler:edit" class="menu"
|
||||
@click="emit('edit')"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="忽略(快捷键:`)">
|
||||
<IconWrapper>
|
||||
<Icon icon="fluent:delete-20-regular" class="menu"
|
||||
@click="emit('remove')"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="收藏(快捷键:Enter)">
|
||||
<IconWrapper>
|
||||
<Icon icon="ph:star" class="menu"
|
||||
@click="emit('collect')"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="跳过(快捷键:Tab)">
|
||||
<IconWrapper>
|
||||
<Icon icon="icon-park-outline:go-ahead" class="menu"
|
||||
@click="emit('skip')"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.options {
|
||||
margin-top: 10rem;
|
||||
display: flex;
|
||||
gap: 15rem;
|
||||
font-size: 18rem;
|
||||
}
|
||||
</style>
|
||||
@@ -10,12 +10,10 @@ import Statistics from "@/components/Practice/Statistics.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus";
|
||||
import {useSettingStore} from "@/stores/setting";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {Article, DefaultArticle, TranslateType} from "@/types.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {renewSectionTexts, renewSectionTranslates} from "@/hooks/translate.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import EditSingleArticleModal from "@/components/Article/EditSingleArticleModal.vue";
|
||||
import PracticeArticle from "@/components/Practice/PracticeArticle/PracticeArticle.vue";
|
||||
import PracticeWord from "@/components/Practice/PracticeWord/PracticeWord.vue";
|
||||
|
||||
const practiceStore = usePracticeStore()
|
||||
const store = useBaseStore()
|
||||
@@ -33,45 +31,6 @@ watch(practiceStore, () => {
|
||||
practiceStore.correctRate = 100 - Math.trunc(((practiceStore.wrongWordNumber) / (practiceStore.inputWordNumber)) * 100)
|
||||
})
|
||||
|
||||
let wordData = $ref({
|
||||
words: [],
|
||||
index: -1
|
||||
})
|
||||
|
||||
let articleData = $ref({
|
||||
article: cloneDeep(DefaultArticle),
|
||||
sectionIndex: 0,
|
||||
sentenceIndex: 0,
|
||||
wordIndex: 0,
|
||||
stringIndex: 0,
|
||||
})
|
||||
|
||||
watch(() => store.load, n => {
|
||||
if (n) {
|
||||
getCurrentPractice()
|
||||
}
|
||||
})
|
||||
|
||||
watch([
|
||||
() => store.current.index,
|
||||
() => store.current.dictType,
|
||||
() => store.currentDict.chapterIndex,
|
||||
() => store.currentDict.chapterWordNumber,
|
||||
], n => {
|
||||
getCurrentPractice()
|
||||
})
|
||||
|
||||
function getCurrentPractice() {
|
||||
// console.log('store.currentDict',store.currentDict)
|
||||
wordData.words = cloneDeep(store.chapter)
|
||||
wordData.index = 0
|
||||
console.log('wordData', wordData)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
})
|
||||
|
||||
function write() {
|
||||
// console.log('write')
|
||||
settingStore.dictation = true
|
||||
@@ -81,7 +40,7 @@ function write() {
|
||||
//TODO 需要判断是否已忽略
|
||||
function repeat() {
|
||||
// console.log('repeat')
|
||||
getCurrentPractice()
|
||||
// getCurrentPractice()
|
||||
emitter.emit(EventKey.resetWord)
|
||||
}
|
||||
|
||||
@@ -109,6 +68,7 @@ function test() {
|
||||
<Toolbar/>
|
||||
<!-- <BaseButton @click="test">test</BaseButton>-->
|
||||
<PracticeArticle v-if="store.isArticle"/>
|
||||
<PracticeWord v-else/>
|
||||
<Footer/>
|
||||
</div>
|
||||
<Statistics
|
||||
|
||||
@@ -126,7 +126,7 @@ function edit(val: Article) {
|
||||
|
||||
<template>
|
||||
<div class="practice-article">
|
||||
<div class="swiper-wrapper content">
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-list" :class="`step${tabIndex}`">
|
||||
<div class="swiper-item">
|
||||
<TypingArticle
|
||||
|
||||
@@ -12,6 +12,7 @@ import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Options from "@/components/Practice/Options.vue";
|
||||
|
||||
interface IProps {
|
||||
article: Article,
|
||||
@@ -432,31 +433,12 @@ function toggleCollect() {
|
||||
<header>
|
||||
<div class="title">{{ props.article.title }}</div>
|
||||
<div class="titleTranslate" v-if="settingStore.translate">{{ props.article.titleTranslate }}</div>
|
||||
<div class="options">
|
||||
<Tooltip title="编辑(快捷键:Ctrl + E)">
|
||||
<IconWrapper>
|
||||
<Icon icon="tabler:edit" class="menu"
|
||||
@click="emit('edit',props.article)"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="忽略(快捷键:`)">
|
||||
<IconWrapper>
|
||||
<Icon icon="fluent:delete-20-regular" class="menu"
|
||||
@click="tabIndex = 1"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="收藏(快捷键:Enter)">
|
||||
<IconWrapper>
|
||||
<Icon :icon="`ph:star${collectIndex > -1?'-fill':''}`" class="menu"
|
||||
@click="toggleCollect"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="跳过(快捷键:Tab)">
|
||||
<IconWrapper>
|
||||
<Icon icon="icon-park-outline:go-ahead" class="menu"
|
||||
@click="emit('next')"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<div class="options-wrapper">
|
||||
<Options
|
||||
@edit="emit('edit',props.article)"
|
||||
@collect="toggleCollect"
|
||||
@skip="emit('next')"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div class="article-content" ref="articleWrapperRef">
|
||||
@@ -557,7 +539,7 @@ $article-width: 1000px;
|
||||
font-size: 20rem;
|
||||
}
|
||||
|
||||
.options {
|
||||
.options-wrapper {
|
||||
position: absolute;
|
||||
right: 20rem;
|
||||
top: 0;
|
||||
|
||||
@@ -1,9 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import WordPanel from "@/components/Practice/PracticeWord/WordPanel.vue";
|
||||
import TypingWord from "@/components/Practice/PracticeWord/TypingWord.vue";
|
||||
import {$ref} from "vue/macros";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {onMounted, watch} from "vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
|
||||
let wordData = $ref({
|
||||
words: [],
|
||||
index: -1
|
||||
})
|
||||
let index = $ref(0)
|
||||
|
||||
watch([
|
||||
() => store.load,
|
||||
() => store.current.index,
|
||||
() => store.current.dictType,
|
||||
() => store.currentDict.chapterIndex,
|
||||
() => store.currentDict.chapterWordNumber,
|
||||
], n => {
|
||||
getCurrentPractice()
|
||||
})
|
||||
|
||||
function getCurrentPractice() {
|
||||
// console.log('store.currentDict',store.currentDict)
|
||||
wordData.words = cloneDeep(store.chapter)
|
||||
wordData.index = 0
|
||||
console.log('wordData', wordData)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getCurrentPractice()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<div class="practice-word">
|
||||
<TypingWord/>
|
||||
<div class="panel-wrapper">
|
||||
<WordPanel :list="[]" v-model:index="index"/>
|
||||
<!-- <WordPanel :list="data.words" v-model:index="data.index"/>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -13,7 +13,7 @@ import {Icon} from "@iconify/vue";
|
||||
import VolumeIcon from "@/components/VolumeIcon.vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import WordPanel from "./WordPanel.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import Options from "@/components/Practice/Options.vue";
|
||||
|
||||
interface IProps {
|
||||
words: Word[],
|
||||
@@ -37,7 +37,6 @@ let wrong = $ref('')
|
||||
let showFullWord = $ref(false)
|
||||
//输入锁定,因为跳转到下一个单词有延时,如果重复在延时期间内重复输入,导致会跳转N次
|
||||
let inputLock = $ref(false)
|
||||
let activeBtnIndex = $ref(-1)
|
||||
let wordRepeatCount = $ref(0)
|
||||
const store = useBaseStore()
|
||||
const practiceStore = usePracticeStore()
|
||||
@@ -150,12 +149,8 @@ function prev() {
|
||||
data.index--
|
||||
}
|
||||
|
||||
function ignore() {
|
||||
activeBtnIndex = 2
|
||||
function skip() {
|
||||
next(false)
|
||||
setTimeout(() => {
|
||||
activeBtnIndex = -1
|
||||
}, 200)
|
||||
}
|
||||
|
||||
function collect() {
|
||||
@@ -164,10 +159,6 @@ function collect() {
|
||||
store.collect.words.push(word)
|
||||
store.collect.chapterWords = [store.collect.words]
|
||||
}
|
||||
activeBtnIndex = 1
|
||||
setTimeout(() => {
|
||||
activeBtnIndex = -1
|
||||
}, 200)
|
||||
}
|
||||
|
||||
function remove() {
|
||||
@@ -176,11 +167,7 @@ function remove() {
|
||||
store.skip.words.push(word)
|
||||
store.skip.chapterWords = [store.skip.words]
|
||||
}
|
||||
activeBtnIndex = 0
|
||||
next(false)
|
||||
setTimeout(() => {
|
||||
activeBtnIndex = -1
|
||||
}, 200)
|
||||
}
|
||||
|
||||
function onKeyUp(e: KeyboardEvent) {
|
||||
@@ -283,7 +270,7 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
remove()
|
||||
break
|
||||
case ShortKeyMap.Ignore:
|
||||
ignore()
|
||||
skip()
|
||||
e.preventDefault()
|
||||
break
|
||||
case ShortKeyMap.Show:
|
||||
@@ -292,9 +279,6 @@ async function onKeyDown(e: KeyboardEvent) {
|
||||
}
|
||||
break
|
||||
}
|
||||
setTimeout(() => {
|
||||
activeBtnIndex = -1
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,30 +331,11 @@ useOnKeyboardEventListener(onKeyDown, onKeyUp)
|
||||
<VolumeIcon ref="volumeIconRef" :simple="true" @click="playWordAudio(word.name)"/>
|
||||
</div>
|
||||
<div class="phonetic">{{ settingStore.wordSoundType === 'us' ? word.usphone : word.ukphone }}</div>
|
||||
<div class="options">
|
||||
<Tooltip title="忽略(快捷键:`)">
|
||||
<IconWrapper>
|
||||
<Icon icon="fluent:delete-20-regular" class="menu"
|
||||
:active="activeBtnIndex === 0"
|
||||
@click="remove"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="收藏(快捷键:Enter)">
|
||||
<IconWrapper>
|
||||
<Icon icon="ph:star" class="menu"
|
||||
@click="collect"
|
||||
:active="activeBtnIndex === 1"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
<Tooltip title="跳过(快捷键:Tab)">
|
||||
<IconWrapper>
|
||||
<Icon icon="icon-park-outline:go-ahead" class="menu"
|
||||
@click="ignore"
|
||||
:active="activeBtnIndex === 2"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<WordPanel :list="data.words" v-model:index="data.index"/>
|
||||
<Options
|
||||
@remove="remove"
|
||||
@skip="skip"
|
||||
@collect="collect"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -433,14 +398,7 @@ useOnKeyboardEventListener(onKeyDown, onKeyUp)
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
margin-top: 10rem;
|
||||
display: flex;
|
||||
gap: 25rem;
|
||||
font-size: 18rem;
|
||||
}
|
||||
|
||||
.phonetic, .translate, .options {
|
||||
.phonetic, .translate {
|
||||
font-size: 20rem;
|
||||
margin-left: -30rem;
|
||||
transition: all .3s;
|
||||
|
||||
Reference in New Issue
Block a user