feat:add shuffle mode
This commit is contained in:
22
components.d.ts
vendored
22
components.d.ts
vendored
@@ -38,14 +38,30 @@ declare module 'vue' {
|
||||
IconFluentAdd16Regular: typeof import('~icons/fluent/add16-regular')['default']
|
||||
IconFluentAdd20Filled: typeof import('~icons/fluent/add20-filled')['default']
|
||||
IconFluentAdd20Regular: typeof import('~icons/fluent/add20-regular')['default']
|
||||
IconFluentAddCircle20Filled: typeof import('~icons/fluent/add-circle20-filled')['default']
|
||||
IconFluentAddSquare20Regular: typeof import('~icons/fluent/add-square20-regular')['default']
|
||||
IconFluentArrowBounce20Regular: typeof import('~icons/fluent/arrow-bounce20-regular')['default']
|
||||
IconFluentArrowCircleRight16Regular: typeof import('~icons/fluent/arrow-circle-right16-regular')['default']
|
||||
IconFluentArrowClockwise20Regular: typeof import('~icons/fluent/arrow-clockwise20-regular')['default']
|
||||
IconFluentArrowClockwise32Filled: typeof import('~icons/fluent/arrow-clockwise32-filled')['default']
|
||||
IconFluentArrowClockwise32Regular: typeof import('~icons/fluent/arrow-clockwise32-regular')['default']
|
||||
IconFluentArrowCounterclockwise32Filled: typeof import('~icons/fluent/arrow-counterclockwise32-filled')['default']
|
||||
IconFluentArrowCounterclockwise32Regular: typeof import('~icons/fluent/arrow-counterclockwise32-regular')['default']
|
||||
IconFluentArrowLeft16Regular: typeof import('~icons/fluent/arrow-left16-regular')['default']
|
||||
IconFluentArrowMove20Regular: typeof import('~icons/fluent/arrow-move20-regular')['default']
|
||||
IconFluentArrowRight16Regular: typeof import('~icons/fluent/arrow-right16-regular')['default']
|
||||
IconFluentArrowShuffle16Regular: typeof import('~icons/fluent/arrow-shuffle16-regular')['default']
|
||||
IconFluentArrowShuffle20Filled: typeof import('~icons/fluent/arrow-shuffle20-filled')['default']
|
||||
IconFluentArrowShuffle20Regular: typeof import('~icons/fluent/arrow-shuffle20-regular')['default']
|
||||
IconFluentArrowShuffle24Regular: typeof import('~icons/fluent/arrow-shuffle24-regular')['default']
|
||||
IconFluentArrowShuffle28Filled: typeof import('~icons/fluent/arrow-shuffle28-filled')['default']
|
||||
IconFluentArrowShuffle28Regular: typeof import('~icons/fluent/arrow-shuffle28-regular')['default']
|
||||
IconFluentArrowSort20Regular: typeof import('~icons/fluent/arrow-sort20-regular')['default']
|
||||
IconFluentArrowSwap20Regular: typeof import('~icons/fluent/arrow-swap20-regular')['default']
|
||||
IconFluentBookLetter20Regular: typeof import('~icons/fluent/book-letter20-regular')['default']
|
||||
IconFluentBookNumber20Filled: typeof import('~icons/fluent/book-number20-filled')['default']
|
||||
IconFluentBookNumber20Regular: typeof import('~icons/fluent/book-number20-regular')['default']
|
||||
IconFluentCalendarEdit20Regular: typeof import('~icons/fluent/calendar-edit20-regular')['default']
|
||||
IconFluentCheckmark20Regular: typeof import('~icons/fluent/checkmark20-regular')['default']
|
||||
IconFluentCheckmarkCircle16Filled: typeof import('~icons/fluent/checkmark-circle16-filled')['default']
|
||||
IconFluentCheckmarkCircle16Regular: typeof import('~icons/fluent/checkmark-circle16-regular')['default']
|
||||
@@ -53,16 +69,20 @@ declare module 'vue' {
|
||||
IconFluentChevronLeft20Filled: typeof import('~icons/fluent/chevron-left20-filled')['default']
|
||||
IconFluentChevronLeft28Filled: typeof import('~icons/fluent/chevron-left28-filled')['default']
|
||||
IconFluentDatabasePerson20Regular: typeof import('~icons/fluent/database-person20-regular')['default']
|
||||
IconFluentDataUsageEdit20Regular: typeof import('~icons/fluent/data-usage-edit20-regular')['default']
|
||||
IconFluentDelete20Regular: typeof import('~icons/fluent/delete20-regular')['default']
|
||||
IconFluentDismiss20Regular: typeof import('~icons/fluent/dismiss20-regular')['default']
|
||||
IconFluentDismissCircle16Regular: typeof import('~icons/fluent/dismiss-circle16-regular')['default']
|
||||
IconFluentDismissCircle20Filled: typeof import('~icons/fluent/dismiss-circle20-filled')['default']
|
||||
IconFluentDocumentEdit20Regular: typeof import('~icons/fluent/document-edit20-regular')['default']
|
||||
IconFluentErrorCircle20Filled: typeof import('~icons/fluent/error-circle20-filled')['default']
|
||||
IconFluentEye16Regular: typeof import('~icons/fluent/eye16-regular')['default']
|
||||
IconFluentEyeOff16Regular: typeof import('~icons/fluent/eye-off16-regular')['default']
|
||||
IconFluentHome20Regular: typeof import('~icons/fluent/home20-regular')['default']
|
||||
IconFluentKeyboardLayoutFloat20Regular: typeof import('~icons/fluent/keyboard-layout-float20-regular')['default']
|
||||
IconFluentLayoutColumnTwoEdit20Regular: typeof import('~icons/fluent/layout-column-two-edit20-regular')['default']
|
||||
IconFluentMyLocation20Regular: typeof import('~icons/fluent/my-location20-regular')['default']
|
||||
IconFluentNoteEdit20Regular: typeof import('~icons/fluent/note-edit20-regular')['default']
|
||||
IconFluentPaddingLeft20Regular: typeof import('~icons/fluent/padding-left20-regular')['default']
|
||||
IconFluentPerson20Regular: typeof import('~icons/fluent/person20-regular')['default']
|
||||
IconFluentPlay20Regular: typeof import('~icons/fluent/play20-regular')['default']
|
||||
@@ -72,6 +92,8 @@ declare module 'vue' {
|
||||
IconFluentSearch24Regular: typeof import('~icons/fluent/search24-regular')['default']
|
||||
IconFluentSettings20Regular: typeof import('~icons/fluent/settings20-regular')['default']
|
||||
IconFluentShieldQuestion20Regular: typeof import('~icons/fluent/shield-question20-regular')['default']
|
||||
IconFluentSlideTextEdit20Regular: typeof import('~icons/fluent/slide-text-edit20-regular')['default']
|
||||
IconFluentSlideTextTitleEdit20Regular: typeof import('~icons/fluent/slide-text-title-edit20-regular')['default']
|
||||
IconFluentSpeakerEdit20Regular: typeof import('~icons/fluent/speaker-edit20-regular')['default']
|
||||
IconFluentSpeakerSettings20Regular: typeof import('~icons/fluent/speaker-settings20-regular')['default']
|
||||
IconFluentStar12Regular: typeof import('~icons/fluent/star12-regular')['default']
|
||||
|
||||
@@ -7,7 +7,7 @@ interface IProps {
|
||||
disabled?: boolean
|
||||
loading?: boolean
|
||||
size?: 'small' | 'normal' | 'large',
|
||||
type?: 'primary' | 'link' | 'info'
|
||||
type?: 'primary' | 'link' | 'info' | 'orange'
|
||||
}
|
||||
|
||||
withDefaults(defineProps<IProps>(), {
|
||||
@@ -97,7 +97,7 @@ defineEmits(['click'])
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:hover:not(.disabled) {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
@@ -120,6 +120,11 @@ defineEmits(['click'])
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
&.orange {
|
||||
background: #FACC15;
|
||||
color: black;
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Article, TaskWords, Word, WordPracticeMode} from "@/types/types.ts";
|
||||
import { Article, TaskWords, Word, WordPracticeMode } from "@/types/types.ts";
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { getDefaultWord } from "@/types/func.ts";
|
||||
@@ -87,7 +87,7 @@ export function useArticleOptions() {
|
||||
|
||||
export function getCurrentStudyWord(): TaskWords {
|
||||
const store = useBaseStore()
|
||||
let data = {new: [], review: [], write: []}
|
||||
let data = {new: [], review: [], write: [], shuffle: []}
|
||||
let dict = store.sdict;
|
||||
let isTest = false
|
||||
let words = dict.words.slice()
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {onMounted, provide, ref, watch} from "vue";
|
||||
import { onMounted, provide, ref, watch } from "vue";
|
||||
|
||||
import Statistics from "@/pages/word/Statistics.vue";
|
||||
import {emitter, EventKey, useEvents} from "@/utils/eventBus.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {Dict, PracticeData, WordPracticeType, ShortcutKey, TaskWords, Word, WordPracticeMode} from "@/types/types.ts";
|
||||
import {useDisableEventListener, useOnKeyboardEventListener, useStartKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import { emitter, EventKey, useEvents } from "@/utils/eventBus.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
import { Dict, PracticeData, WordPracticeType, ShortcutKey, TaskWords, Word, WordPracticeMode } from "@/types/types.ts";
|
||||
import { useDisableEventListener, useOnKeyboardEventListener, useStartKeyboardEventListener } from "@/hooks/event.ts";
|
||||
import useTheme from "@/hooks/theme.ts";
|
||||
import {getCurrentStudyWord, useWordOptions} from "@/hooks/dict.ts";
|
||||
import {_getDictDataByUrl, cloneDeep, resourceWrap, shuffle} from "@/utils";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import { getCurrentStudyWord, useWordOptions } from "@/hooks/dict.ts";
|
||||
import { _getDictDataByUrl, cloneDeep, resourceWrap, shuffle } from "@/utils";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import Footer from "@/pages/word/components/Footer.vue";
|
||||
import Panel from "@/components/Panel.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
@@ -19,15 +19,15 @@ import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import WordList from "@/components/list/WordList.vue";
|
||||
import TypeWord from "@/pages/word/components/TypeWord.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
import { usePracticeStore } from "@/stores/practice.ts";
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {getDefaultDict, getDefaultWord} from "@/types/func.ts";
|
||||
import { getDefaultDict, getDefaultWord } from "@/types/func.ts";
|
||||
import ConflictNotice from "@/components/ConflictNotice.vue";
|
||||
import PracticeLayout from "@/components/PracticeLayout.vue";
|
||||
|
||||
import {DICT_LIST, PracticeSaveWordKey} from "@/config/env.ts";
|
||||
import {ToastInstance} from "@/components/base/toast/type.ts";
|
||||
import { DICT_LIST, PracticeSaveWordKey } from "@/config/env.ts";
|
||||
import { ToastInstance } from "@/components/base/toast/type.ts";
|
||||
|
||||
const {
|
||||
isWordCollect,
|
||||
@@ -125,26 +125,33 @@ function initData(initVal: TaskWords, init: boolean = false) {
|
||||
}
|
||||
} else {
|
||||
taskWords = initVal
|
||||
if (taskWords.new.length === 0) {
|
||||
if (taskWords.review.length) {
|
||||
settingStore.wordPracticeType = WordPracticeType.Identify
|
||||
statStore.step = 3
|
||||
data.words = taskWords.review
|
||||
} else {
|
||||
if (taskWords.write.length) {
|
||||
if (taskWords.shuffle.length === 0) {
|
||||
if (taskWords.new.length === 0) {
|
||||
if (taskWords.review.length) {
|
||||
settingStore.wordPracticeType = WordPracticeType.Identify
|
||||
data.words = taskWords.write
|
||||
statStore.step = 6
|
||||
statStore.step = 3
|
||||
data.words = taskWords.review
|
||||
} else {
|
||||
Toast.warning('没有可学习的单词!')
|
||||
router.push('/word')
|
||||
if (taskWords.write.length) {
|
||||
settingStore.wordPracticeType = WordPracticeType.Identify
|
||||
data.words = taskWords.write
|
||||
statStore.step = 6
|
||||
} else {
|
||||
Toast.warning('没有可学习的单词!')
|
||||
router.push('/word')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
settingStore.wordPracticeType = WordPracticeType.FollowWrite
|
||||
data.words = taskWords.new
|
||||
statStore.step = 0
|
||||
}
|
||||
} else {
|
||||
settingStore.wordPracticeType = WordPracticeType.FollowWrite
|
||||
data.words = taskWords.new
|
||||
statStore.step = 0
|
||||
settingStore.wordPracticeType = WordPracticeType.Dictation
|
||||
data.words = taskWords.shuffle
|
||||
statStore.step = 10
|
||||
}
|
||||
|
||||
data.index = 0
|
||||
data.wrongWords = []
|
||||
data.excludeWords = []
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
import { useRouter } from "vue-router";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import { _getAccomplishDate, _getDictDataByUrl, resourceWrap, 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 { DictResource, WordPracticeMode } from "@/types/types.ts";
|
||||
import { watch } from "vue";
|
||||
import { getCurrentStudyWord } from "@/hooks/dict.ts";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
@@ -23,6 +23,7 @@ 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";
|
||||
|
||||
|
||||
const store = useBaseStore()
|
||||
@@ -35,7 +36,8 @@ let isSaveData = $ref(false)
|
||||
let currentStudy = $ref({
|
||||
new: [],
|
||||
review: [],
|
||||
write: []
|
||||
write: [],
|
||||
shuffle: [],
|
||||
})
|
||||
|
||||
watch(() => store.load, n => {
|
||||
@@ -93,6 +95,7 @@ function startPractice() {
|
||||
}
|
||||
|
||||
let showPracticeSettingDialog = $ref(false)
|
||||
let showShufflePracticeSettingDialog = $ref(false)
|
||||
let showChangeLastPracticeIndexDialog = $ref(false)
|
||||
let showPracticeWordListDialog = $ref(false)
|
||||
|
||||
@@ -156,6 +159,19 @@ async function savePracticeSetting() {
|
||||
currentStudy = getCurrentStudyWord()
|
||||
}
|
||||
|
||||
async function onShufflePracticeSettingOk(total) {
|
||||
window.umami?.track('startSuffleStudyWord', {
|
||||
name: store.sdict.name,
|
||||
index: store.sdict.lastLearnIndex,
|
||||
perDayStudyNumber: store.sdict.perDayStudyNumber,
|
||||
custom: store.sdict.custom,
|
||||
complete: store.sdict.complete,
|
||||
wordPracticeMode: settingStore.wordPracticeMode
|
||||
})
|
||||
currentStudy.shuffle = shuffle(store.sdict.words).slice(0, total)
|
||||
nav('practice-words/' + store.sdict.id, {}, currentStudy)
|
||||
}
|
||||
|
||||
async function saveLastPracticeIndex(e) {
|
||||
Toast.success('修改成功')
|
||||
runtimeStore.editDict.lastLearnIndex = e
|
||||
@@ -171,93 +187,123 @@ const {
|
||||
isFetching
|
||||
} = useFetch(resourceWrap(DICT_LIST.WORD.RECOMMENDED)).json()
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasePage>
|
||||
<div class="card flex gap-10">
|
||||
<div class="flex-1 flex flex-col gap-2">
|
||||
<div class="flex">
|
||||
<div class="bg-third px-3 h-14 rounded-md flex items-center ">
|
||||
<span @click="goDictDetail(store.sdict)"
|
||||
class="text-lg font-bold cursor-pointer">{{ store.sdict.name || '请选择词典开始学习' }}</span>
|
||||
<BaseIcon title="切换词典"
|
||||
class="ml-4"
|
||||
@click="router.push('/dict-list')"
|
||||
>
|
||||
<IconFluentArrowSort20Regular v-if="store.sdict.name"/>
|
||||
<IconFluentAdd20Filled v-else/>
|
||||
</BaseIcon>
|
||||
<div class="card flex gap-8">
|
||||
<div class="flex-1 flex flex-col justify-between">
|
||||
<div class="flex gap-3">
|
||||
<div class="p-1 center rounded-full bg-white">
|
||||
<IconFluentBookNumber20Filled class="text-xl color-blue"/>
|
||||
</div>
|
||||
<div
|
||||
@click="goDictDetail(store.sdict)"
|
||||
class="text-2xl font-bold cursor-pointer">
|
||||
{{ store.sdict.name || '请选择词典开始学习' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-end gap-space">
|
||||
<div class="flex-1">
|
||||
<div class="text-sm flex justify-between">
|
||||
<span>{{ progressTextLeft }}</span>
|
||||
<span>{{ progressTextRight }} / {{ store.sdict.words.length }}</span>
|
||||
</div>
|
||||
<Progress class="mt-1" :percentage="store.currentStudyProgress" :show-text="false"></Progress>
|
||||
<div class="mt-4 flex flex-col gap-2">
|
||||
<div class="">当前进度:{{ progressTextLeft }}</div>
|
||||
<Progress :percentage="store.currentStudyProgress" :show-text="false"></Progress>
|
||||
<div class="text-sm flex justify-between">
|
||||
<span>已完成 {{ progressTextRight }} 词 / 共 {{ store.sdict.words.length }} 词</span>
|
||||
<span>
|
||||
预计完成日期:{{ _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)">
|
||||
<div class="color-blue cursor-pointer">更改</div>
|
||||
<BaseButton type="info"
|
||||
:disabled="!store.sdict.name"
|
||||
>
|
||||
<div class="center gap-1">
|
||||
<IconFluentSlideTextTitleEdit20Regular/>
|
||||
<span>更改进度</span>
|
||||
</div>
|
||||
</BaseButton>
|
||||
</PopConfirm>
|
||||
|
||||
</div>
|
||||
<div class="text-sm text-align-end">
|
||||
预计完成日期:{{ _getAccomplishDate(store.sdict.words.length, store.sdict.perDayStudyNumber) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-3/10 flex flex-col justify-evenly">
|
||||
<div class="center gap-2">
|
||||
<span class="text-xl">{{ isSaveData ? '上次学习任务' : '今日任务' }}</span>
|
||||
<span class="color-blue cursor-pointer" @click="showPracticeWordListDialog = true">词表</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 center rounded-full bg-white ">
|
||||
<IconFluentStar20Filled class="text-lg color-amber"/>
|
||||
</div>
|
||||
<div class="text-xl font-bold">
|
||||
{{ isSaveData ? '上次学习任务' : '今日任务' }}
|
||||
</div>
|
||||
<span class="color-blue cursor-pointer" @click="showPracticeWordListDialog = true">词表</span>
|
||||
|
||||
</div>
|
||||
<div class="flex gap-1 items-center">
|
||||
每日目标
|
||||
<div style="color:#ac6ed1;"
|
||||
class="bg-third px-2 h-10 flex center text-2xl rounded">
|
||||
{{ store.sdict.id ? store.sdict.perDayStudyNumber : 0 }}
|
||||
</div>
|
||||
个单词
|
||||
<PopConfirm
|
||||
:disabled="!isSaveData"
|
||||
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
|
||||
@confirm="check(()=>showPracticeSettingDialog = true)">
|
||||
<BaseButton
|
||||
:disabled="!store.sdict.name"
|
||||
type="info" size="small">更改
|
||||
</BaseButton>
|
||||
</PopConfirm>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex-1 flex flex-col items-center">
|
||||
<div class="flex mt-4 justify-between">
|
||||
<div class="w-31% box-border flex flex-col center rounded-xl p-2 bg-[var(--bg-history)]">
|
||||
<div class="text-4xl font-bold">{{ currentStudy.new.length }}</div>
|
||||
<div class="text">新词</div>
|
||||
<div class="text-sm">新词数</div>
|
||||
</div>
|
||||
<template v-if="settingStore.wordPracticeMode === WordPracticeMode.System">
|
||||
<div class="flex-1 flex flex-col items-center">
|
||||
<div class="w-31% box-border flex flex-col center rounded-xl p-2 bg-[var(--bg-history)]">
|
||||
<div class="text-4xl font-bold">{{ currentStudy.review.length }}</div>
|
||||
<div class="text">复习上次</div>
|
||||
<div class="text-sm">复习上次</div>
|
||||
</div>
|
||||
<div class="flex-1 flex flex-col items-center">
|
||||
<div class="text-4xl font-bold">{{ currentStudy.write.length }}
|
||||
</div>
|
||||
<div class="text">复习之前</div>
|
||||
<div class="w-31% box-border flex flex-col center rounded-xl p-2 bg-[var(--bg-history)]">
|
||||
<div class="text-4xl font-bold">{{ currentStudy.write.length }}</div>
|
||||
<div class="text-sm">复习之前</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-end justify-around ">
|
||||
<div class="flex gap-1 items-center">
|
||||
每日目标
|
||||
<div style="color:#ac6ed1;"
|
||||
class="bg-third px-2 h-10 flex center text-2xl rounded">
|
||||
{{ store.sdict.id ? store.sdict.perDayStudyNumber : 0 }}
|
||||
</div>
|
||||
个单词
|
||||
<PopConfirm
|
||||
:disabled="!isSaveData"
|
||||
title="当前存在未完成的学习任务,修改会重新生成学习任务,是否继续?"
|
||||
@confirm="check(()=>showPracticeSettingDialog = true)">
|
||||
<span class="color-blue cursor-pointer">更改</span>
|
||||
</PopConfirm>
|
||||
<div class="flex items-end mt-4">
|
||||
<BaseButton size="large"
|
||||
class="flex-1"
|
||||
:disabled="!store.sdict.name"
|
||||
:loading="loading"
|
||||
@click="startPractice">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="line-height-[2]">{{ isSaveData ? '继续学习' : '开始学习' }}</span>
|
||||
<IconFluentArrowCircleRight16Regular class="text-xl"/>
|
||||
</div>
|
||||
</BaseButton>
|
||||
<BaseButton size="large" type="orange"
|
||||
:disabled="(!store.sdict.name || !store.sdict.lastLearnIndex)"
|
||||
: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>
|
||||
<BaseButton size="large" :disabled="!store.sdict.name"
|
||||
:loading="loading"
|
||||
@click="startPractice">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="line-height-[2]">{{ isSaveData ? '继续学习' : '开始学习' }}</span>
|
||||
<IconFluentArrowCircleRight16Regular class="text-xl"/>
|
||||
</div>
|
||||
</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -317,6 +363,10 @@ const {
|
||||
v-model="showPracticeWordListDialog"
|
||||
/>
|
||||
|
||||
<ShufflePracticeSettingDialog
|
||||
v-model="showShufflePracticeSettingDialog"
|
||||
@ok="onShufflePracticeSettingOk"/>
|
||||
|
||||
<CollectNotice/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ const status = $computed(() => {
|
||||
case 8:
|
||||
str += '默写之前学习'
|
||||
break
|
||||
case 10:
|
||||
str += '随机复习'
|
||||
break
|
||||
}
|
||||
return str
|
||||
})
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {_getAccomplishDays} from "@/utils";
|
||||
import Radio from "@/components/base/radio/Radio.vue";
|
||||
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
|
||||
import { _getAccomplishDays } from "@/utils";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import Checkbox from "@/components/base/checkbox/Checkbox.vue";
|
||||
import Slider from "@/components/base/Slider.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {defineAsyncComponent, watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import { defineAsyncComponent, watch } from "vue";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
import ChangeLastPracticeIndexDialog from "@/pages/word/components/ChangeLastPracticeIndexDialog.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
|
||||
68
src/pages/word/components/ShufflePracticeSettingDialog.vue
Normal file
68
src/pages/word/components/ShufflePracticeSettingDialog.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Slider from "@/components/base/Slider.vue";
|
||||
import { defineAsyncComponent, watch } from "vue";
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
const store = useBaseStore()
|
||||
|
||||
const model = defineModel()
|
||||
|
||||
const emit = defineEmits<{
|
||||
ok: [val: number];
|
||||
}>()
|
||||
|
||||
let num = $ref(0)
|
||||
let min = $ref(0)
|
||||
|
||||
watch(() => model.value, (n) => {
|
||||
if (n) {
|
||||
num = Math.floor(store.sdict.lastLearnIndex / 3)
|
||||
min = num < 10 ? num : 10
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model="model" title="随机复习设置"
|
||||
:footer="true"
|
||||
@ok="emit('ok',num)">
|
||||
<div class="target-modal color-main">
|
||||
<div class="flex gap-4 items-end mb-2">
|
||||
<span>随机复习:<span class="font-bold">{{ store.sdict.name }}</span></span>
|
||||
<span class="text-3xl mx-2 lh">{{ num }}</span>个单词
|
||||
</div>
|
||||
<div class="flex gap-space">
|
||||
<span class="shrink-0">随机数量</span>
|
||||
<Slider :min="min"
|
||||
:step="10"
|
||||
show-text
|
||||
class="mt-1"
|
||||
:max="store.sdict.lastLearnIndex"
|
||||
v-model="num"/>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.target-modal {
|
||||
width: 30rem;
|
||||
padding: 0 var(--space);
|
||||
|
||||
.lh {
|
||||
color: rgb(176, 116, 211)
|
||||
}
|
||||
|
||||
.mode-item {
|
||||
@apply w-50% border border-blue border-solid p-2 rounded-lg cursor-pointer;
|
||||
}
|
||||
|
||||
.active {
|
||||
@apply bg-blue color-white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -200,6 +200,7 @@ export interface TaskWords {
|
||||
new: Word[],
|
||||
review: Word[],
|
||||
write: Word[],
|
||||
shuffle: Word[],
|
||||
}
|
||||
|
||||
export class DictId {
|
||||
|
||||
@@ -8,6 +8,8 @@ export default defineConfig({
|
||||
'bg-third': 'bg-[var(--color-third)]',
|
||||
'bg-card-active': 'bg-[var(--color-card-active)]',
|
||||
'bg-item': 'bg-[var(--color-item-bg)]',
|
||||
'bg-reverse-white': 'bg-[var(--color-reverse-white)]',
|
||||
'bg-reverse-black': 'bg-[var(--color-reverse-black)]',
|
||||
'color-main': 'color-[var(--color-main-text)]',
|
||||
'gap-space': 'gap-[var(--space)]',
|
||||
'p-space': 'p-[var(--space)]',
|
||||
|
||||
Reference in New Issue
Block a user