This commit is contained in:
Zyronon
2025-11-16 03:53:11 +08:00
parent 17a400c414
commit 9032711601
3 changed files with 123 additions and 61 deletions

1
components.d.ts vendored
View File

@@ -57,6 +57,7 @@ declare module 'vue' {
IconFluentCheckmarkCircle16Regular: typeof import('~icons/fluent/checkmark-circle16-regular')['default']
IconFluentCheckmarkCircle20Filled: typeof import('~icons/fluent/checkmark-circle20-filled')['default']
IconFluentCheckmarkCircle20Regular: typeof import('~icons/fluent/checkmark-circle20-regular')['default']
IconFluentChevronDown20Regular: typeof import('~icons/fluent/chevron-down20-regular')['default']
IconFluentChevronLeft20Filled: typeof import('~icons/fluent/chevron-left20-filled')['default']
IconFluentChevronLeft28Filled: typeof import('~icons/fluent/chevron-left28-filled')['default']
IconFluentCrown20Regular: typeof import('~icons/fluent/crown20-regular')['default']

View File

@@ -3,15 +3,23 @@
import BackIcon from "@/components/BackIcon.vue";
import { useAttrs } from "vue";
defineProps<{
interface IProps {
title: string;
}>()
showBackIcon?: boolean;
}
withDefaults(defineProps<IProps>(), {
title: '',
showBackIcon: true,
})
const attrs = useAttrs()
</script>
<template>
<div class="mb-3 text-xl font-bold relative">
<BackIcon class="z-2 relative" v-bind="attrs"/>
<div class="mb-3 text-xl font-bold relative min-h-8">
<BackIcon class="z-2 relative" v-bind="attrs" v-if="showBackIcon" />
<span class="absolute text-center w-full left-0" @click.stop>{{ title }}</span>
</div>
</template>

View File

@@ -1,28 +1,29 @@
<script setup lang="ts">
import {useBaseStore} from "@/stores/base.ts";
import {useRouter} from "vue-router";
import { useBaseStore } from "@/stores/base.ts";
import { useRouter } from "vue-router";
import BaseIcon from "@/components/BaseIcon.vue";
import {_getAccomplishDate, _getDictDataByUrl, resourceWrap, shuffle, useNav} from "@/utils";
import { _getAccomplishDate, _getDictDataByUrl, resourceWrap, shuffle, useNav } from "@/utils";
import BasePage from "@/components/BasePage.vue";
import {DictResource, WordPracticeMode} from "@/types/types.ts";
import {watch} from "vue";
import {getCurrentStudyWord} from "@/hooks/dict.ts";
import {useRuntimeStore} from "@/stores/runtime.ts";
import { DictResource, WordPracticeMode } from "@/types/types.ts";
import { watch } from "vue";
import { getCurrentStudyWord } from "@/hooks/dict.ts";
import { useRuntimeStore } from "@/stores/runtime.ts";
import Book from "@/components/Book.vue";
import PopConfirm from "@/components/PopConfirm.vue";
import Progress from '@/components/base/Progress.vue';
import Toast from '@/components/base/toast/Toast.ts';
import BaseButton from "@/components/BaseButton.vue";
import {getDefaultDict} from "@/types/func.ts";
import { getDefaultDict } from "@/types/func.ts";
import DeleteIcon from "@/components/icon/DeleteIcon.vue";
import PracticeSettingDialog from "@/pages/word/components/PracticeSettingDialog.vue";
import ChangeLastPracticeIndexDialog from "@/pages/word/components/ChangeLastPracticeIndexDialog.vue";
import {useSettingStore} from "@/stores/setting.ts";
import {useFetch} from "@vueuse/core";
import {CAN_REQUEST, DICT_LIST, PracticeSaveWordKey} from "@/config/env.ts";
import {myDictList} from "@/apis";
import { useSettingStore } from "@/stores/setting.ts";
import { useFetch } from "@vueuse/core";
import { CAN_REQUEST, DICT_LIST, PracticeSaveWordKey } from "@/config/env.ts";
import { myDictList } from "@/apis";
import PracticeWordListDialog from "@/pages/word/components/PracticeWordListDialog.vue";
import ShufflePracticeSettingDialog from "@/pages/word/components/ShufflePracticeSettingDialog.vue";
import Header from "@/components/Header.vue";
const store = useBaseStore()
@@ -208,45 +209,58 @@ const {
<IconFluentBookNumber20Filled class="text-xl color-link"/>
</div>
<div
@click="goDictDetail(store.sdict)"
class="text-2xl font-bold cursor-pointer">
{{ store.sdict.name || '请选择词典开始学习' }}
@click="goDictDetail(store.sdict)"
class="text-2xl font-bold cursor-pointer">
{{ store.sdict.name || '当前无正在学习的词典' }}
</div>
</div>
<div class="mt-4 flex flex-col gap-2">
<div class="">当前进度{{ progressTextLeft }}</div>
<Progress size="large" :percentage="store.currentStudyProgress" :show-text="false"></Progress>
<div class="text-sm flex justify-between">
<span>已完成 {{ progressTextRight }} / {{ store.sdict.words.length }} </span>
<span v-if="store.sdict.id">
<template v-if="store.sdict.id">
<div class="mt-4 flex flex-col gap-2">
<div class="">当前进度{{ progressTextLeft }}</div>
<Progress size="large" :percentage="store.currentStudyProgress" :show-text="false"></Progress>
<div class="text-sm flex justify-between">
<span>已完成 {{ progressTextRight }} / {{ store.sdict.words.length }} </span>
<span v-if="store.sdict.id">
预计完成日期{{ _getAccomplishDate(store.sdict.words.length, store.sdict.perDayStudyNumber) }}
</span>
</div>
</div>
<div class="flex mt-4 gap-4">
<BaseButton type="info" @click="router.push('/dict-list')">
<div class="center gap-1">
<IconFluentArrowSwap20Regular/>
<span>{{ store.sdict.name ? '切换' : '选择' }}词典</span>
</div>
</BaseButton>
<PopConfirm
:disabled="!isSaveData"
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
@confirm="check(()=>showChangeLastPracticeIndexDialog = true)">
<BaseButton type="info"
v-if="store.sdict.id"
>
</div>
<div class="flex mt-4 gap-4">
<BaseButton type="info" @click="router.push('/dict-list')">
<div class="center gap-1">
<IconFluentSlideTextTitleEdit20Regular/>
<span>更改进度</span>
<IconFluentArrowSwap20Regular/>
<span>选择词典</span>
</div>
</BaseButton>
</PopConfirm>
<PopConfirm
:disabled="!isSaveData"
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
@confirm="check(()=>showChangeLastPracticeIndexDialog = true)">
<BaseButton type="info"
v-if="store.sdict.id"
>
<div class="center gap-1">
<IconFluentSlideTextTitleEdit20Regular/>
<span>更改进度</span>
</div>
</BaseButton>
</PopConfirm>
</div>
</template>
<div class="flex items-center gap-4 mt-2 flex-1" v-else>
<div class="title">请选择一本词典开始学习</div>
<BaseButton type="primary" size="large" @click="router.push('/dict-list')">
<div class="center gap-1">
<IconFluentAdd16Regular/>
<span>选择词典</span>
</div>
</BaseButton>
</div>
</div>
<div class="flex-1">
<div class="flex-1" :class="!store.sdict.id && 'opacity-30 cursor-not-allowed'">
<div class="flex justify-between">
<div class="flex items-center gap-3">
<div class="p-2 center rounded-full bg-white ">
@@ -270,11 +284,11 @@ const {
</div>
个单词
<PopConfirm
:disabled="!isSaveData"
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
@confirm="check(()=>showPracticeSettingDialog = true)">
:disabled="!isSaveData"
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
@confirm="check(()=>showPracticeSettingDialog = true)">
<BaseButton
type="info" size="small">更改
type="info" size="small">更改
</BaseButton>
</PopConfirm>
</div>
@@ -297,6 +311,7 @@ const {
</div>
<div class="flex items-end mt-4">
<BaseButton size="large"
v-if="false"
class="flex-1"
:disabled="!store.sdict.id"
:loading="loading"
@@ -306,11 +321,49 @@ const {
<IconFluentArrowCircleRight16Regular class="text-xl"/>
</div>
</BaseButton>
<div
class="w-full flex box-border rounded-lg cp color-white">
<div class="flex-1 center gap-2 py-1 bg-[var(--btn-primary)] hover:opacity-50">
<span class="line-height-[2]">{{ isSaveData ? '继续学习' : '开始学习' }}</span>
<IconFluentArrowCircleRight16Regular class="text-xl"/>
</div>
<div class="relative group">
<div
class="w-10 h-full center bg-[var(--btn-primary)] hover:bg-gray border-solid border-2 border-l-gray border-transparent box-border">
<IconFluentChevronDown20Regular/>
</div>
<div
class="absolute z-2 left-1/2 -translate-x-1/2 mt-2 w-40 bg-white border rounded shadow opacity-110 scale-95
group-hover:opacity-100 group-hover:scale-100
transition-all duration-150 pointer-events-none group-hover:pointer-events-auto"
>
<BaseButton
v-for="i in 3"
size="large" type="orange"
:loading="loading"
@click="check(()=>showShufflePracticeSettingDialog = true)">
<div class="flex items-center gap-2">
<span class="line-height-[2]">随机复习</span>
<IconFluentArrowShuffle20Filled class="text-xl"/>
</div>
</BaseButton>
</div>
</div>
</div>
<BaseButton
v-if="store.sdict.id && store.sdict.lastLearnIndex"
size="large" type="orange"
:loading="loading"
@click="check(()=>showShufflePracticeSettingDialog = true)">
v-if="store.sdict.id && store.sdict.lastLearnIndex"
size="large" type="orange"
:loading="loading"
@click="check(()=>showShufflePracticeSettingDialog = true)">
<div class="flex items-center gap-2">
<span class="line-height-[2]">随机复习</span>
<IconFluentArrowShuffle20Filled class="text-xl"/>
@@ -362,23 +415,23 @@ const {
</BasePage>
<PracticeSettingDialog
:show-left-option="false"
v-model="showPracticeSettingDialog"
@ok="savePracticeSetting"/>
:show-left-option="false"
v-model="showPracticeSettingDialog"
@ok="savePracticeSetting"/>
<ChangeLastPracticeIndexDialog
v-model="showChangeLastPracticeIndexDialog"
@ok="saveLastPracticeIndex"
v-model="showChangeLastPracticeIndexDialog"
@ok="saveLastPracticeIndex"
/>
<PracticeWordListDialog
:data="currentStudy"
v-model="showPracticeWordListDialog"
:data="currentStudy"
v-model="showPracticeWordListDialog"
/>
<ShufflePracticeSettingDialog
v-model="showShufflePracticeSettingDialog"
@ok="onShufflePracticeSettingOk"/>
v-model="showShufflePracticeSettingDialog"
@ok="onShufflePracticeSettingOk"/>
</template>