diff --git a/app/components/setting/WordSetting.vue b/app/components/setting/WordSetting.vue index 4404fd41f..a45961c5a 100644 --- a/app/components/setting/WordSetting.vue +++ b/app/components/setting/WordSetting.vue @@ -48,6 +48,22 @@ const settingStore = useSettingStore() +
+ + + + + + + + +
diff --git a/app/components/word/Statistics.vue b/app/components/word/Statistics.vue index 9a16ed627..418ded9be 100644 --- a/app/components/word/Statistics.vue +++ b/app/components/word/Statistics.vue @@ -2,7 +2,7 @@ import { useBaseStore } from '@/core/stores/base.ts' import { BaseButton, Progress } from '@/base' import type { PracticeData } from '@/core/composables/practice-words/practice-word-session.ts' -import { ShortcutKey } from '@/core/types/enum.ts' +import { ShortcutKey, WordPracticeMode } from '@/core/types/enum.ts' import { emitter, useEvents } from '@/core/utils/eventBus.ts' import { useSettingStore } from '@/core/stores/setting.ts' import { usePracticeStore } from '@/core/stores/practice.ts' @@ -13,6 +13,12 @@ import isoWeek from 'dayjs/plugin/isoWeek' import { msToHourMinute } from '@/core/utils' import ChannelIcons from '@/components/channel-icons/ChannelIcons.vue' import { useI18n } from 'vue-i18n' +import saveAs from 'file-saver' +import { + buildFreePracticeSummary, + renderFreePracticeSummaryMarkdown, + renderFreePracticeSummaryText, +} from '@/core/composables/practice-words/practice-summary.ts' dayjs.extend(isoWeek) dayjs.extend(isBetween) @@ -28,6 +34,33 @@ const statStore = usePracticeStore() const model = defineModel({ default: false }) let list = $ref([]) const practiceData = inject('practiceData')! +const isFreePractice = $computed(() => settingStore.wordPracticeMode === WordPracticeMode.Free) +const practiceSummary = $computed(() => + buildFreePracticeSummary(practiceData.spellingMistakes, settingStore.freePracticeSummaryWrongThreshold) +) + +const summaryDocumentInfo = $computed(() => ({ + dictName: store.sdict.name, + startedAt: dayjs(statStore.startDate).format('YYYY-MM-DD HH:mm:ss'), + duration: msToHourMinute(statStore.spend, true), + totalWords: statStore.total, + newWords: statStore.newWordNumber, + reviewWords: statStore.reviewWordNumber, +})) + +function sanitizeFileName(value: string): string { + return value.replace(/[\\/:*?"<>|]/g, '-').trim() || '未命名词典' +} + +function exportPracticeSummary(format: 'txt' | 'md') { + const content = + format === 'md' + ? renderFreePracticeSummaryMarkdown(practiceSummary, summaryDocumentInfo) + : renderFreePracticeSummaryText(practiceSummary, summaryDocumentInfo) + const type = format === 'md' ? 'text/markdown;charset=utf-8' : 'text/plain;charset=utf-8' + const fileName = `自由练习总结-${sanitizeFileName(store.sdict.name)}-${dayjs().format('YYYY-MM-DD-HH-mm-ss')}.${format}` + saveAs(new Blob(['\uFEFF', content], { type }), fileName) +} function calcWeekList() { // 获取本周的起止时间 @@ -99,7 +132,7 @@ const encouragementText = $computed(() => {