This commit is contained in:
Zyronon
2025-12-30 20:10:13 +08:00
committed by GitHub
parent 8d778a8b44
commit 7b9be69838
22 changed files with 2188 additions and 1126 deletions

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

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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) {

View File

@@ -2,6 +2,10 @@
let logList = [
{
date: '2025/12/30',
content: '移除“继续默写”选项',
},
{
date: '2025/12/29',
content: '单词练习界面,底部工具栏新增音频设置按钮',
},
{

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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 />

View File

@@ -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',
}

View File

@@ -16,7 +16,6 @@ export const EventKey = {
editDict: 'editDict',
openMyDictDialog: 'openMyDictDialog',
stateInitEnd: 'stateInitEnd',
randomWrite: 'randomWrite',
}
export function useEvent(key: string, func: any) {

View File

@@ -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(),