wip
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,6 @@
|
||||
--color-item-border: rgb(226, 226, 226);
|
||||
|
||||
--color-tooltip-bg: white;
|
||||
--color-tooltip-shadow: #d9d9d9;
|
||||
--color-font-2: rgb(46, 46, 46);
|
||||
--color-font-3: rgb(102, 116, 135);
|
||||
--color-font-active-1: white;
|
||||
@@ -70,6 +69,8 @@
|
||||
--bg-card-secend: rgb(247, 247, 247);
|
||||
|
||||
--bg-book: rgb(226 232 240);
|
||||
|
||||
--color-line: rgb(226, 226, 226);
|
||||
}
|
||||
|
||||
html.dark {
|
||||
@@ -91,8 +92,7 @@ html.dark {
|
||||
--bg-history: rgb(43, 45, 48);
|
||||
--color-item-border: rgb(41, 41, 41);
|
||||
|
||||
--color-tooltip-bg: #252525;
|
||||
--color-tooltip-shadow: #3b3b3b;
|
||||
--color-tooltip-bg: #35373a;
|
||||
--color-font-2: rgba(255, 255, 255, 0.5);
|
||||
--color-font-3: rgba(255, 255, 255, 0.3);
|
||||
|
||||
@@ -116,6 +116,7 @@ html.dark {
|
||||
|
||||
--bg-book: #35373a;
|
||||
|
||||
--color-line: rgb(66, 66, 66);
|
||||
}
|
||||
|
||||
@media (max-width: 1720px) {
|
||||
@@ -403,7 +404,7 @@ a {
|
||||
|
||||
.line {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid var(--color-item-border);
|
||||
border-bottom: 1px solid var(--color-line);
|
||||
@apply hover:text-blue-700;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ interface IProps {
|
||||
disabled?: boolean
|
||||
loading?: boolean
|
||||
size?: 'small' | 'normal' | 'large'
|
||||
type?: 'primary' | 'link' | 'info' | 'orange'
|
||||
type?: 'primary' | 'info' | 'orange'
|
||||
}
|
||||
|
||||
withDefaults(defineProps<IProps>(), {
|
||||
@@ -27,12 +27,7 @@ defineEmits(['click'])
|
||||
:class="[active && 'active', size, type, (disabled || loading) && 'disabled']"
|
||||
>
|
||||
<span :style="{ opacity: loading ? 0 : 1 }"><slot></slot></span>
|
||||
<IconEosIconsLoading
|
||||
v-if="loading"
|
||||
class="loading"
|
||||
width="18"
|
||||
:color="type === 'info' ? '#000000' : '#ffffff'"
|
||||
/>
|
||||
<IconEosIconsLoading v-if="loading" class="loading" width="18" :color="type === 'info' ? '#000000' : '#ffffff'" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</template>
|
||||
@@ -45,7 +40,7 @@ defineEmits(['click'])
|
||||
--btn-info: white;
|
||||
--btn-info-hover: #eaeaea;
|
||||
--btn-orange: #facc15;
|
||||
--btn-orange-hover: #fbe27e;
|
||||
--btn-orange-hover: #bfac61;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
@@ -124,15 +119,6 @@ html.dark {
|
||||
}
|
||||
}
|
||||
|
||||
&.link {
|
||||
border-radius: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&:hover:not(.disabled) {
|
||||
border-bottom: 2px solid var(--color-font-2);
|
||||
}
|
||||
}
|
||||
|
||||
&.info {
|
||||
background: var(--btn-info);
|
||||
border: 1px solid var(--color-main-text);
|
||||
|
||||
@@ -18,9 +18,9 @@ export default {
|
||||
validator(value) {
|
||||
// Validate that array items have the correct structure
|
||||
if (Array.isArray(value)) {
|
||||
return value.every(item =>
|
||||
typeof item === 'object' &&
|
||||
item !== null &&
|
||||
return value.every(item =>
|
||||
typeof item === 'object' &&
|
||||
item !== null &&
|
||||
typeof item.text === 'string' &&
|
||||
['normal', 'bold', 'red', 'redBold'].includes(item.type)
|
||||
)
|
||||
@@ -114,8 +114,8 @@ export default {
|
||||
<div ref="tip" class="pop-confirm-content shadow-2xl">
|
||||
<div class="w-52 title-content">
|
||||
{this.titleItems.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
<div
|
||||
key={index}
|
||||
style={this.getTextStyle(item.type)}
|
||||
class="title-item"
|
||||
>
|
||||
@@ -140,17 +140,14 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.pop-confirm-content {
|
||||
position: fixed;
|
||||
background: var(--color-tooltip-bg);
|
||||
padding: 1rem;
|
||||
border-radius: .6rem;
|
||||
transform: translate(-50%, calc(-100% - .6rem));
|
||||
z-index: 999;
|
||||
@apply fixed z-9999 shadow-2xl rounded-lg p-3;
|
||||
|
||||
.title-content {
|
||||
.title-item {
|
||||
margin-bottom: 0.25rem;
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="relative group">
|
||||
<div
|
||||
class="more w-10 rounded-r-lg h-full center border-solid border-1 border-l-gray/50 border-transparent box-border transition-all duration-300"
|
||||
>
|
||||
<div class="more w-10 rounded-r-lg h-full center box-border transition-all duration-300">
|
||||
<IconFluentChevronDown20Regular />
|
||||
</div>
|
||||
<div
|
||||
@@ -34,6 +32,8 @@
|
||||
.primary-btn {
|
||||
.more {
|
||||
background: var(--btn-primary);
|
||||
border: 1.5px solid transparent;
|
||||
border-left-color: #69788e;
|
||||
&:hover {
|
||||
background: var(--btn-primary-hover);
|
||||
}
|
||||
@@ -44,7 +44,8 @@
|
||||
.more {
|
||||
background: var(--btn-orange);
|
||||
color: black;
|
||||
border-left-color: black;
|
||||
border: 1px solid transparent;
|
||||
border-left-color: #cfb752;
|
||||
&:hover {
|
||||
background: var(--btn-orange-hover);
|
||||
}
|
||||
|
||||
@@ -72,14 +72,8 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tip {
|
||||
position: fixed;
|
||||
font-size: 1rem;
|
||||
z-index: 9999;
|
||||
border-radius: .3rem;
|
||||
padding: 0.4rem .8rem;
|
||||
color: var(--color-font-1);
|
||||
background: var(--color-tooltip-bg);
|
||||
max-width: 22rem;
|
||||
box-shadow: 0 0 6px 1px var(--color-tooltip-shadow);
|
||||
@apply fixed z-9999 shadow-xl border-item-solid rounded-md px-2.5 py-1.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -245,7 +245,8 @@ $time: 0.3s;
|
||||
}
|
||||
|
||||
.modal {
|
||||
@apply relative bg-second overflow-hidden flex flex-col transition-all duration-300;
|
||||
@apply relative overflow-hidden flex flex-col transition-all duration-300;
|
||||
background: var(--color-card-bg);
|
||||
|
||||
.close {
|
||||
@apply absolute right-1.2rem top-1.2rem z-999;
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import { Word } from "@/types/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import BaseList from "@/components/list/BaseList.vue";
|
||||
import { usePlayWordAudio } from "@/hooks/sound.ts";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import WordItem from "@/components/WordItem.vue";
|
||||
|
||||
withDefaults(defineProps<{
|
||||
list: Word[],
|
||||
showTranslate?: boolean
|
||||
showWord?: boolean
|
||||
}>(), {
|
||||
list: [],
|
||||
showTranslate: true,
|
||||
showWord: true
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
click: [val: { item: Word, index: number }],
|
||||
title: [val: { item: Word, index: number }],
|
||||
}>()
|
||||
|
||||
const listRef: any = $ref(null as any)
|
||||
|
||||
function scrollToBottom() {
|
||||
listRef?.scrollToBottom()
|
||||
}
|
||||
|
||||
function scrollToItem(index: number) {
|
||||
listRef?.scrollToItem(index)
|
||||
}
|
||||
|
||||
const playWordAudio = usePlayWordAudio()
|
||||
|
||||
defineExpose({ scrollToBottom, scrollToItem })
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BaseList ref="listRef" @click="(e: any) => emit('click', e)" :list="list" v-bind="$attrs">
|
||||
<template v-slot:prefix="{ item, index }">
|
||||
<slot name="prefix" :item="item" :index="index"></slot>
|
||||
</template>
|
||||
<template v-slot="{ item, index }">
|
||||
<div class="item-title">
|
||||
<span class="text-sm">{{ index + 1 }}.</span>
|
||||
<span class="word" :class="!showWord && 'word-shadow'">{{ item.word }}</span>
|
||||
<span class="phonetic" :class="!showWord && 'word-shadow'">{{ item.phonetic0 }}</span>
|
||||
<VolumeIcon class="volume" @click="playWordAudio(item.word)"></VolumeIcon>
|
||||
</div>
|
||||
<div class="item-sub-title flex flex-col gap-2" v-if="item.trans.length && showTranslate">
|
||||
<div v-for="v in item.trans">
|
||||
<Tooltip v-if="v.cn.length > 30" :key="item.word" :title="v.pos + ' ' + v.cn">
|
||||
<span>{{ v.pos + ' ' + v.cn.slice(0, 30) + '...' }}</span>
|
||||
</Tooltip>
|
||||
<span v-else>{{ v.pos + ' ' + v.cn }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:suffix="{ item, index }">
|
||||
<slot name="suffix" :item="item" :index="index"></slot>
|
||||
</template>
|
||||
</BaseList>
|
||||
</template>
|
||||
@@ -58,7 +58,7 @@ let show = $ref(false)
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-right: 1px solid gainsboro;
|
||||
border-right: 2px solid var(--color-line);
|
||||
|
||||
.tabs {
|
||||
padding: 1rem;
|
||||
|
||||
@@ -544,8 +544,8 @@ provide('currentPractice', currentPractice)
|
||||
<div class="name">记录</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{statStore.spend }}分钟</div>
|
||||
<!-- <div class="num">{{ Math.floor(statStore.spend / 1000 / 60) }}分钟</div> -->
|
||||
<!-- <div class="num">{{statStore.spend }}分钟</div>-->
|
||||
<div class="num">{{ Math.floor(statStore.spend / 1000 / 60) }}分钟</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">时间</div>
|
||||
</div>
|
||||
|
||||
@@ -223,9 +223,9 @@ function handleChange(e: any) {
|
||||
return v.map((w, j) => {
|
||||
for (let k = 0; k < lrcList.length; k++) {
|
||||
let s = lrcList[k]
|
||||
let d = Comparison.default.cosine.similarity(w.text, s.text)
|
||||
d = Comparison.default.levenshtein.similarity(w.text, s.text)
|
||||
d = Comparison.default.longestCommonSubsequence.similarity(w.text, s.text)
|
||||
// let d = Comparison.default.cosine.similarity(w.text, s.text)
|
||||
// d = Comparison.default.levenshtein.similarity(w.text, s.text)
|
||||
let d = Comparison.default.longestCommonSubsequence.similarity(w.text, s.text)
|
||||
// d = Comparison.default.metricLcs.similarity(w.text, s.text)
|
||||
// console.log(w.text, s.text, d)
|
||||
if (d >= 0.8) {
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
let logList = [
|
||||
{
|
||||
date: '2025/12/30',
|
||||
content: '移除“继续默写”选项',
|
||||
},
|
||||
{
|
||||
date: '2025/12/29',
|
||||
content: '单词练习界面,底部工具栏新增音频设置按钮',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -457,7 +457,7 @@ function transferOk() {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.col-line {
|
||||
border-right: 2px solid gainsboro;
|
||||
border-right: 2px solid var(--color-line);
|
||||
}
|
||||
|
||||
.setting {
|
||||
|
||||
@@ -16,22 +16,10 @@ import {
|
||||
WordPracticeStage,
|
||||
WordPracticeType,
|
||||
} from '@/types/types.ts'
|
||||
import {
|
||||
useDisableEventListener,
|
||||
useOnKeyboardEventListener,
|
||||
useStartKeyboardEventListener,
|
||||
} from '@/hooks/event.ts'
|
||||
import { useDisableEventListener, useOnKeyboardEventListener, useStartKeyboardEventListener } from '@/hooks/event.ts'
|
||||
import useTheme from '@/hooks/theme.ts'
|
||||
import { getCurrentStudyWord, useWordOptions } from '@/hooks/dict.ts'
|
||||
import {
|
||||
_getDictDataByUrl,
|
||||
_nextTick,
|
||||
cloneDeep,
|
||||
isMobile,
|
||||
loadJsLib,
|
||||
resourceWrap,
|
||||
shuffle,
|
||||
} from '@/utils'
|
||||
import { _getDictDataByUrl, _nextTick, cloneDeep, isMobile, loadJsLib, resourceWrap, shuffle } from '@/utils'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import Footer from '@/pages/word/components/Footer.vue'
|
||||
import Panel from '@/components/Panel.vue'
|
||||
@@ -385,14 +373,16 @@ function wordLoop() {
|
||||
|
||||
let toastInstance: ToastInstance = null
|
||||
|
||||
function nextStage(originList, log) {
|
||||
function nextStage(originList: Word[], log: string = '', toast: boolean = false) {
|
||||
//每次都判断,因为每次都可能新增已掌握的单词
|
||||
let list = originList.filter(v => !data.excludeWords.includes(v.word))
|
||||
console.log(log)
|
||||
statStore.stage = statStore.nextStage
|
||||
if (list.length) {
|
||||
if (toastInstance) toastInstance.close()
|
||||
toastInstance = Toast.info('输入完成后按空格键切换下一个', { duration: 5000 })
|
||||
if (toast) {
|
||||
if (toastInstance) toastInstance.close()
|
||||
toastInstance = Toast.info('输入完成后按空格键切换下一个', { duration: 5000 })
|
||||
}
|
||||
data.words = list
|
||||
data.index = 0
|
||||
} else {
|
||||
@@ -426,10 +416,7 @@ async function next(isTyping: boolean = true) {
|
||||
} else {
|
||||
if (data.index === data.words.length - 1) {
|
||||
//如果手动敲的,才轮询
|
||||
if (
|
||||
(statStore.stage === WordPracticeStage.FollowWriteNewWord || isTypingWrongWord.value) &&
|
||||
isTyping
|
||||
) {
|
||||
if ((statStore.stage === WordPracticeStage.FollowWriteNewWord || isTypingWrongWord.value) && isTyping) {
|
||||
if (settingStore.wordPracticeType !== WordPracticeType.Spell) {
|
||||
//回到最后一组的开始位置
|
||||
data.index = Math.floor(data.index / groupSize) * groupSize
|
||||
@@ -461,19 +448,19 @@ async function next(isTyping: boolean = true) {
|
||||
|
||||
if (settingStore.wordPracticeMode === WordPracticeMode.System) {
|
||||
if (statStore.stage === WordPracticeStage.FollowWriteNewWord) {
|
||||
nextStage(shuffle(taskWords.new), '开始听写新词')
|
||||
nextStage(shuffle(taskWords.new), '开始听写新词', true)
|
||||
} else if (statStore.stage === WordPracticeStage.ListenNewWord) {
|
||||
nextStage(shuffle(taskWords.new), '开始默写新词')
|
||||
} else if (statStore.stage === WordPracticeStage.DictationNewWord) {
|
||||
nextStage(taskWords.review, '开始自测昨日')
|
||||
} else if (statStore.stage === WordPracticeStage.IdentifyReview) {
|
||||
nextStage(shuffle(taskWords.review), '开始听写上次')
|
||||
nextStage(shuffle(taskWords.review), '开始听写上次', true)
|
||||
} else if (statStore.stage === WordPracticeStage.ListenReview) {
|
||||
nextStage(shuffle(taskWords.review), '开始默写上次')
|
||||
} else if (statStore.stage === WordPracticeStage.DictationReview) {
|
||||
nextStage(taskWords.write, '开始自测之前')
|
||||
} else if (statStore.stage === WordPracticeStage.IdentifyReviewAll) {
|
||||
nextStage(shuffle(taskWords.write), '开始听写之前')
|
||||
nextStage(shuffle(taskWords.write), '开始听写之前', true)
|
||||
} else if (statStore.stage === WordPracticeStage.ListenReviewAll) {
|
||||
nextStage(shuffle(taskWords.write), '开始默写之前')
|
||||
} else if (statStore.stage === WordPracticeStage.DictationReviewAll) {
|
||||
@@ -481,13 +468,13 @@ async function next(isTyping: boolean = true) {
|
||||
}
|
||||
} else if (settingStore.wordPracticeMode === WordPracticeMode.ListenOnly) {
|
||||
if (statStore.stage === WordPracticeStage.ListenNewWord) {
|
||||
nextStage(taskWords.review, '开始听写昨日')
|
||||
nextStage(taskWords.review, '开始听写昨日',true)
|
||||
} else if (statStore.stage === WordPracticeStage.ListenReview) {
|
||||
nextStage(taskWords.write, '开始听写之前')
|
||||
} else if (statStore.stage === WordPracticeStage.ListenReviewAll) complete()
|
||||
} else if (settingStore.wordPracticeMode === WordPracticeMode.DictationOnly) {
|
||||
if (statStore.stage === WordPracticeStage.DictationNewWord) {
|
||||
nextStage(taskWords.review, '开始默写昨日')
|
||||
nextStage(taskWords.review, '开始默写昨日',true)
|
||||
} else if (statStore.stage === WordPracticeStage.DictationReview) {
|
||||
nextStage(taskWords.write, '开始默写之前')
|
||||
} else if (statStore.stage === WordPracticeStage.DictationReviewAll) complete()
|
||||
@@ -501,13 +488,13 @@ async function next(isTyping: boolean = true) {
|
||||
if (statStore.stage === WordPracticeStage.Shuffle) complete()
|
||||
} else if (settingStore.wordPracticeMode === WordPracticeMode.Review) {
|
||||
if (statStore.stage === WordPracticeStage.IdentifyReview) {
|
||||
nextStage(shuffle(taskWords.review), '开始听写昨日')
|
||||
nextStage(shuffle(taskWords.review), '开始听写昨日',true)
|
||||
} else if (statStore.stage === WordPracticeStage.ListenReview) {
|
||||
nextStage(shuffle(taskWords.review), '开始默写昨日')
|
||||
} else if (statStore.stage === WordPracticeStage.DictationReview) {
|
||||
nextStage(taskWords.write, '开始自测之前')
|
||||
} else if (statStore.stage === WordPracticeStage.IdentifyReviewAll) {
|
||||
nextStage(shuffle(taskWords.write), '开始听写之前')
|
||||
nextStage(shuffle(taskWords.write), '开始听写之前',true)
|
||||
} else if (statStore.stage === WordPracticeStage.ListenReviewAll) {
|
||||
nextStage(shuffle(taskWords.write), '开始默写之前')
|
||||
} else if (statStore.stage === WordPracticeStage.DictationReviewAll) complete()
|
||||
@@ -677,9 +664,7 @@ async function continueStudy() {
|
||||
console.log('没学完,强行跳过')
|
||||
store.sdict.lastLearnIndex = store.sdict.lastLearnIndex + statStore.newWordNumber
|
||||
// 忽略单词数
|
||||
const ignoreCount = ignoreList.filter(word =>
|
||||
store.sdict.words.some(w => w.word.toLowerCase() === word)
|
||||
).length
|
||||
const ignoreCount = ignoreList.filter(word => store.sdict.words.some(w => w.word.toLowerCase() === word)).length
|
||||
// 如果lastLearnIndex已经超过可学单词数,则判定完成
|
||||
if (store.sdict.lastLearnIndex + ignoreCount >= store.sdict.length) {
|
||||
store.sdict.complete = true
|
||||
@@ -725,18 +710,9 @@ function randomWrite() {
|
||||
settingStore.dictation = true
|
||||
}
|
||||
|
||||
function nextRandomWrite() {
|
||||
setPracticeWordCache(null)
|
||||
console.log('继续随机默写')
|
||||
initData(getCurrentStudyWord())
|
||||
randomWrite()
|
||||
showStatDialog = false
|
||||
}
|
||||
|
||||
useEvents([
|
||||
[EventKey.repeatStudy, repeat],
|
||||
[EventKey.continueStudy, continueStudy],
|
||||
[EventKey.randomWrite, nextRandomWrite],
|
||||
[ShortcutKey.ShowWord, show],
|
||||
[ShortcutKey.Previous, prev],
|
||||
[ShortcutKey.Next, skip],
|
||||
@@ -752,7 +728,6 @@ useEvents([
|
||||
[ShortcutKey.ToggleConciseMode, toggleConciseMode],
|
||||
[ShortcutKey.TogglePanel, togglePanel],
|
||||
[ShortcutKey.RandomWrite, randomWrite],
|
||||
[ShortcutKey.NextRandomWrite, nextRandomWrite],
|
||||
])
|
||||
</script>
|
||||
|
||||
@@ -767,11 +742,7 @@ useEvents([
|
||||
<div class="word">{{ prevWord.word }}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div
|
||||
class="center gap-2 cursor-pointer float-right mr-3"
|
||||
@click="next(false)"
|
||||
v-if="nextWord"
|
||||
>
|
||||
<div class="center gap-2 cursor-pointer float-right mr-3" @click="next(false)" v-if="nextWord">
|
||||
<Tooltip :title="`下一个(${settingStore.shortcutKeyMap[ShortcutKey.Next]})`">
|
||||
<div class="word" :class="settingStore.dictation && 'word-shadow'">
|
||||
{{ nextWord.word }}
|
||||
@@ -780,13 +751,7 @@ useEvents([
|
||||
<IconFluentArrowRight16Regular class="arrow" width="22" />
|
||||
</div>
|
||||
</div>
|
||||
<TypeWord
|
||||
ref="typingRef"
|
||||
:word="word"
|
||||
@wrong="onTypeWrong"
|
||||
@complete="next"
|
||||
@know="onWordKnow"
|
||||
/>
|
||||
<TypeWord ref="typingRef" :word="word" @wrong="onTypeWrong" @complete="next" @know="onWordKnow" />
|
||||
</div>
|
||||
</template>
|
||||
共{{ Math.ceil(store.sdict.length / store.sdict.perDayStudyNumber) }}组
|
||||
@@ -798,16 +763,12 @@ useEvents([
|
||||
|
||||
<GroupList
|
||||
@click="jumpToGroup"
|
||||
v-if="
|
||||
taskWords.new.length && settingStore.wordPracticeMode !== WordPracticeMode.Shuffle
|
||||
"
|
||||
v-if="taskWords.new.length && settingStore.wordPracticeMode !== WordPracticeMode.Shuffle"
|
||||
/>
|
||||
<BaseIcon
|
||||
v-if="
|
||||
taskWords.new.length &&
|
||||
![WordPracticeMode.Review, WordPracticeMode.Shuffle].includes(
|
||||
settingStore.wordPracticeMode
|
||||
)
|
||||
![WordPracticeMode.Review, WordPracticeMode.Shuffle].includes(settingStore.wordPracticeMode)
|
||||
"
|
||||
@click="continueStudy"
|
||||
:title="`下一组(${settingStore.shortcutKeyMap[ShortcutKey.NextChapter]})`"
|
||||
@@ -815,10 +776,7 @@ useEvents([
|
||||
<IconFluentArrowRight16Regular class="arrow" width="22" />
|
||||
</BaseIcon>
|
||||
|
||||
<BaseIcon
|
||||
@click="randomWrite"
|
||||
:title="`随机默写(${settingStore.shortcutKeyMap[ShortcutKey.RandomWrite]})`"
|
||||
>
|
||||
<BaseIcon @click="randomWrite" :title="`随机默写(${settingStore.shortcutKeyMap[ShortcutKey.RandomWrite]})`">
|
||||
<IconFluentArrowShuffle16Regular class="arrow" width="22" />
|
||||
</BaseIcon>
|
||||
</div>
|
||||
|
||||
@@ -142,16 +142,11 @@ function startPractice(practiceMode: WordPracticeMode, resetCache: boolean = fal
|
||||
}
|
||||
|
||||
function freePractice() {
|
||||
startPractice(
|
||||
WordPracticeMode.Free,
|
||||
settingStore.wordPracticeMode !== WordPracticeMode.Free && isSaveData
|
||||
)
|
||||
startPractice(WordPracticeMode.Free, settingStore.wordPracticeMode !== WordPracticeMode.Free && isSaveData)
|
||||
}
|
||||
function systemPractice() {
|
||||
startPractice(
|
||||
settingStore.wordPracticeMode === WordPracticeMode.Free
|
||||
? WordPracticeMode.System
|
||||
: settingStore.wordPracticeMode,
|
||||
settingStore.wordPracticeMode === WordPracticeMode.Free ? WordPracticeMode.System : settingStore.wordPracticeMode,
|
||||
settingStore.wordPracticeMode === WordPracticeMode.Free && isSaveData
|
||||
)
|
||||
}
|
||||
@@ -264,9 +259,7 @@ async function saveLastPracticeIndex(e) {
|
||||
currentStudy = getCurrentStudyWord()
|
||||
}
|
||||
|
||||
const { data: recommendDictList, isFetching } = useFetch(
|
||||
resourceWrap(DICT_LIST.WORD.RECOMMENDED)
|
||||
).json()
|
||||
const { data: recommendDictList, isFetching } = useFetch(resourceWrap(DICT_LIST.WORD.RECOMMENDED)).json()
|
||||
|
||||
let isNewHost = $ref(window.location.host === Host)
|
||||
|
||||
@@ -312,11 +305,7 @@ const systemPracticeText = $computed(() => {
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<Progress
|
||||
size="large"
|
||||
:percentage="store.currentStudyProgress"
|
||||
:show-text="false"
|
||||
></Progress>
|
||||
<Progress size="large" :percentage="store.currentStudyProgress" :show-text="false"></Progress>
|
||||
|
||||
<div class="text-sm flex justify-between">
|
||||
<span>{{ progressTextLeft }}</span>
|
||||
@@ -356,10 +345,7 @@ const systemPracticeText = $computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex-1 w-full mt-4 md:mt-0"
|
||||
:class="!store.sdict.id && 'opacity-30 cursor-not-allowed'"
|
||||
>
|
||||
<div class="flex-1 w-full mt-4 md:mt-0" :class="!store.sdict.id && 'opacity-30 cursor-not-allowed'">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="p-2 center rounded-full bg-white">
|
||||
@@ -368,10 +354,7 @@ const systemPracticeText = $computed(() => {
|
||||
<div class="text-xl font-bold">
|
||||
{{ isSaveData ? '上次任务' : '今日任务' }}
|
||||
</div>
|
||||
<span
|
||||
class="color-link cursor-pointer"
|
||||
v-if="store.sdict.id"
|
||||
@click="showPracticeWordListDialog = true"
|
||||
<span class="color-link cursor-pointer" v-if="store.sdict.id" @click="showPracticeWordListDialog = true"
|
||||
>词表</span
|
||||
>
|
||||
</div>
|
||||
@@ -406,11 +389,7 @@ const systemPracticeText = $computed(() => {
|
||||
</div>
|
||||
<div class="flex items-end mt-4 gap-4 btn-no-margin">
|
||||
<OptionButton
|
||||
:class="
|
||||
settingStore.wordPracticeMode !== WordPracticeMode.Free
|
||||
? 'flex-1 orange-btn'
|
||||
: 'primary-btn'
|
||||
"
|
||||
:class="settingStore.wordPracticeMode !== WordPracticeMode.Free ? 'flex-1 orange-btn' : 'primary-btn'"
|
||||
>
|
||||
<BaseButton
|
||||
size="large"
|
||||
@@ -431,7 +410,7 @@ const systemPracticeText = $computed(() => {
|
||||
settingStore.wordPracticeMode !== WordPracticeMode.System &&
|
||||
settingStore.wordPracticeMode !== WordPracticeMode.Free
|
||||
"
|
||||
@click="startPractice(WordPracticeMode.System,true)"
|
||||
@click="startPractice(WordPracticeMode.System, true)"
|
||||
>
|
||||
智能学习
|
||||
</BaseButton>
|
||||
@@ -440,14 +419,14 @@ const systemPracticeText = $computed(() => {
|
||||
class="w-full"
|
||||
v-if="settingStore.wordPracticeMode !== WordPracticeMode.Review"
|
||||
:disabled="!currentStudy.review.length && !currentStudy.write.length"
|
||||
@click="startPractice(WordPracticeMode.Review,true)"
|
||||
@click="startPractice(WordPracticeMode.Review, true)"
|
||||
>
|
||||
复习
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
v-if="settingStore.wordPracticeMode !== WordPracticeMode.Shuffle"
|
||||
:disabled="store.sdict.lastLearnIndex < 10"
|
||||
:disabled="store.sdict.lastLearnIndex < 10 && !store.sdict.complete"
|
||||
@click="check(() => (showShufflePracticeSettingDialog = true))"
|
||||
>
|
||||
随机复习
|
||||
@@ -456,21 +435,21 @@ const systemPracticeText = $computed(() => {
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
v-if="settingStore.wordPracticeMode !== WordPracticeMode.IdentifyOnly"
|
||||
@click="startPractice(WordPracticeMode.IdentifyOnly,true)"
|
||||
@click="startPractice(WordPracticeMode.IdentifyOnly, true)"
|
||||
>
|
||||
{{ WordPracticeModeNameMap[WordPracticeMode.IdentifyOnly] }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
v-if="settingStore.wordPracticeMode !== WordPracticeMode.ListenOnly"
|
||||
@click="startPractice(WordPracticeMode.ListenOnly,true)"
|
||||
@click="startPractice(WordPracticeMode.ListenOnly, true)"
|
||||
>
|
||||
{{ WordPracticeModeNameMap[WordPracticeMode.ListenOnly] }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
v-if="settingStore.wordPracticeMode !== WordPracticeMode.DictationOnly"
|
||||
@click="startPractice(WordPracticeMode.DictationOnly,true)"
|
||||
@click="startPractice(WordPracticeMode.DictationOnly, true)"
|
||||
>
|
||||
{{ WordPracticeModeNameMap[WordPracticeMode.DictationOnly] }}
|
||||
</BaseButton>
|
||||
@@ -487,9 +466,7 @@ const systemPracticeText = $computed(() => {
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="line-height-[2]">
|
||||
{{
|
||||
settingStore.wordPracticeMode === WordPracticeMode.Free && isSaveData
|
||||
? '继续自由练习'
|
||||
: '自由练习'
|
||||
settingStore.wordPracticeMode === WordPracticeMode.Free && isSaveData ? '继续自由练习' : '自由练习'
|
||||
}}
|
||||
</span>
|
||||
<IconStreamlineColorPenDrawFlat class="text-xl" />
|
||||
@@ -503,11 +480,7 @@ const systemPracticeText = $computed(() => {
|
||||
<div class="flex justify-between">
|
||||
<div class="title">我的词典</div>
|
||||
<div class="flex gap-4 items-center">
|
||||
<PopConfirm
|
||||
title="确认删除所有选中词典?"
|
||||
@confirm="handleBatchDel"
|
||||
v-if="selectIds.length"
|
||||
>
|
||||
<PopConfirm title="确认删除所有选中词典?" @confirm="handleBatchDel" v-if="selectIds.length">
|
||||
<BaseIcon class="del" title="删除">
|
||||
<DeleteIcon />
|
||||
</BaseIcon>
|
||||
@@ -525,9 +498,7 @@ const systemPracticeText = $computed(() => {
|
||||
>
|
||||
{{ isManageDict ? '取消' : '管理词典' }}
|
||||
</div>
|
||||
<div class="color-link cursor-pointer" @click="nav('dict-detail', { isAdd: true })">
|
||||
创建个人词典
|
||||
</div>
|
||||
<div class="color-link cursor-pointer" @click="nav('dict-detail', { isAdd: true })">创建个人词典</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4 flex-wrap mt-4">
|
||||
@@ -565,23 +536,13 @@ const systemPracticeText = $computed(() => {
|
||||
</div>
|
||||
</BasePage>
|
||||
|
||||
<PracticeSettingDialog
|
||||
:show-left-option="false"
|
||||
v-model="showPracticeSettingDialog"
|
||||
@ok="savePracticeSetting"
|
||||
/>
|
||||
<PracticeSettingDialog :show-left-option="false" v-model="showPracticeSettingDialog" @ok="savePracticeSetting" />
|
||||
|
||||
<ChangeLastPracticeIndexDialog
|
||||
v-model="showChangeLastPracticeIndexDialog"
|
||||
@ok="saveLastPracticeIndex"
|
||||
/>
|
||||
<ChangeLastPracticeIndexDialog v-model="showChangeLastPracticeIndexDialog" @ok="saveLastPracticeIndex" />
|
||||
|
||||
<PracticeWordListDialog :data="currentStudy" v-model="showPracticeWordListDialog" />
|
||||
|
||||
<ShufflePracticeSettingDialog
|
||||
v-model="showShufflePracticeSettingDialog"
|
||||
@ok="onShufflePracticeSettingOk"
|
||||
/>
|
||||
<ShufflePracticeSettingDialog v-model="showShufflePracticeSettingDialog" @ok="onShufflePracticeSettingOk" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -318,7 +318,7 @@ const stages = $computed(() => {
|
||||
</div>
|
||||
<div class="progress-wrap flex gap-3 items-center color-gray">
|
||||
<span class="shrink-0">{{ status }}</span>
|
||||
<Progress :percentage="progress" :stroke-width="8" color="#69b1ff" :show-text="false" />
|
||||
<StageProgress :stages="stages" />
|
||||
<div class="num">{{ `${practiceData.index + 1}/${practiceData.words.length}` }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -262,17 +262,6 @@ calcWeekList() // 新增:计算本周学习记录
|
||||
{{ dictIsEnd ? '从头开始练习' : '再来一组' }}
|
||||
</div>
|
||||
</BaseButton>
|
||||
<!-- todo 感觉这里的继续默写有问题,应该是当前组,而不是下一组-->
|
||||
<BaseButton
|
||||
v-if="settingStore.wordPracticeMode !== WordPracticeMode.Review"
|
||||
:keyboard="settingStore.shortcutKeyMap[ShortcutKey.NextRandomWrite]"
|
||||
@click="options(EventKey.randomWrite)"
|
||||
>
|
||||
<div class="center gap-2">
|
||||
<IconFluentPen20Regular />
|
||||
继续默写
|
||||
</div>
|
||||
</BaseButton>
|
||||
<BaseButton @click="$router.back">
|
||||
<div class="center gap-2">
|
||||
<IconFluentHome20Regular />
|
||||
|
||||
@@ -120,7 +120,6 @@ export enum ShortcutKey {
|
||||
ToggleConciseMode = 'ToggleConciseMode',
|
||||
TogglePanel = 'TogglePanel',
|
||||
RandomWrite = 'RandomWrite',
|
||||
NextRandomWrite = 'NextRandomWrite',
|
||||
KnowWord = 'KnowWord',
|
||||
UnknownWord = 'UnknownWord',
|
||||
}
|
||||
@@ -143,7 +142,6 @@ export const DefaultShortcutKeyMap = {
|
||||
[ShortcutKey.ToggleConciseMode]: 'Ctrl+M',
|
||||
[ShortcutKey.TogglePanel]: 'Ctrl+L',
|
||||
[ShortcutKey.RandomWrite]: 'Ctrl+R',
|
||||
[ShortcutKey.NextRandomWrite]: 'Ctrl+Shift+R',
|
||||
[ShortcutKey.KnowWord]: '1',
|
||||
[ShortcutKey.UnknownWord]: '2',
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ export const EventKey = {
|
||||
editDict: 'editDict',
|
||||
openMyDictDialog: 'openMyDictDialog',
|
||||
stateInitEnd: 'stateInitEnd',
|
||||
randomWrite: 'randomWrite',
|
||||
}
|
||||
|
||||
export function useEvent(key: string, func: any) {
|
||||
|
||||
@@ -19,6 +19,7 @@ export default defineConfig({
|
||||
'px-space': 'px-[var(--space)]',
|
||||
'py-space': 'py-[var(--space)]',
|
||||
'border-item': 'border-[var(--color-item-border)]',
|
||||
'border-item-solid': 'border-1 border-solid border-[var(--color-item-border)]',
|
||||
},
|
||||
presets: [
|
||||
presetWind3(),
|
||||
|
||||
Reference in New Issue
Block a user