This commit is contained in:
Zyronon
2025-11-21 21:22:32 +08:00
committed by GitHub
parent 8d6cdd1877
commit 20c20ab3e4
2 changed files with 537 additions and 121 deletions

View File

@@ -1,25 +1,277 @@
<script setup lang="ts">
import { GITHUB, ProjectName } from "@/config/env.ts";
import {APP_NAME, GITHUB} from "@/config/env.ts";
import BaseIcon from "@/components/BaseIcon.vue";
import { defineAsyncComponent } from "vue";
import {defineAsyncComponent, onMounted, ref, watch} from "vue";
import {usePracticeStore} from "@/stores/practice.ts";
import {useBaseStore} from "@/stores/base.ts";
import {msToHourMinute} from "@/utils";
import dayjs from "dayjs";
import BaseButton from "@/components/BaseButton.vue";
import Toast from "@/components/base/toast/Toast.ts";
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
const practiceStore = usePracticeStore()
const baseStore = useBaseStore()
let showWechatDialog = $ref(false)
let showXhsDialog = $ref(false)
let showQQDialog = $ref(false)
let showShareImageDialog = $ref(false)
let isGeneratingImage = $ref(false)
let generatedImageUrl = $ref<string | null>(null)
// 计算学习统计数据
const studyStats = $computed(() => {
const accuracyRate = practiceStore.total === 0 ? 100 : Math.round(((practiceStore.total - practiceStore.wrong) / practiceStore.total) * 100)
const studyTime = msToHourMinute(practiceStore.spend).replace('小时', 'h ').replace('分钟', 'm')
return {
total: practiceStore.total,
newWords: practiceStore.newWordNumber,
review: practiceStore.reviewWordNumber + practiceStore.writeWordNumber,
wrong: practiceStore.wrong,
correct: practiceStore.total - practiceStore.wrong,
accuracy: accuracyRate,
time: studyTime,
date: dayjs().format('MM月DD日'),
dictionary: baseStore.sdict.name || '未知词书'
}
})
// 监听对话框打开事件,自动生成图片
watch(() => showShareImageDialog, (newVal) => {
if (newVal && !generatedImageUrl) {
generateShareImage()
}
})
// 生成分享图片
async function generateShareImage() {
if (isGeneratingImage || generatedImageUrl) return
isGeneratingImage = true
try {
// 创建canvas元素
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// 设置尺寸为1.3倍高度比例 (宽度720高度936)
const width = 720
const height = Math.round(width * 1.3)
canvas.width = width
canvas.height = height
if (!ctx) return
// 创建灰黑色渐变背景
const gradient = ctx.createLinearGradient(0, 0, width, height)
gradient.addColorStop(0, '#1f2937')
gradient.addColorStop(1, '#111827')
ctx.fillStyle = gradient
ctx.fillRect(0, 0, width, height)
// 添加装饰性圆形
ctx.fillStyle = 'rgba(255, 255, 255, 0.05)'
ctx.beginPath()
ctx.arc(width * 0.8, height * 0.2, 60, 0, Math.PI * 2)
ctx.fill()
ctx.beginPath()
ctx.arc(width * 0.2, height * 0.8, 40, 0, Math.PI * 2)
ctx.fill()
// 设置文字样式
ctx.fillStyle = '#ffffff'
ctx.textAlign = 'left'
// 顶部用户信息
const avatarX = width * 0.1
const avatarY = height * 0.08
// 绘制头像背景
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)'
ctx.beginPath()
ctx.arc(avatarX + 25, avatarY + 25, 20, 0, Math.PI * 2)
ctx.fill()
ctx.fillStyle = '#ffffff'
ctx.font = 'bold 18px Arial'
ctx.fillText(baseStore.user?.name || '学习者', avatarX + 60, avatarY + 20)
ctx.font = '14px Arial'
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
ctx.fillText(dayjs().format('YYYY年MM月DD日'), avatarX + 60, avatarY + 40)
// 右上角标签
ctx.textAlign = 'right'
ctx.font = '12px Arial'
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'
ctx.fillText('Type Words | 英语学习', width * 0.9, avatarY + 20)
// 统计数据区域 (三个圆角矩形)
const statsY = height * 0.25
const statWidth = width * 0.25
const statHeight = height * 0.12
const statSpacing = width * 0.05
const stats = [
{ label: '总词数', value: studyStats.total, color: '#60a5fa' },
{ label: '学习时长', value: studyStats.time, color: '#34d399' },
{ label: '正确率', value: studyStats.accuracy + '%', color: '#f59e0b' }
]
stats.forEach((stat, index) => {
const x = width * 0.1 + index * (statWidth + statSpacing)
const y = statsY
// 绘制圆角矩形背景
ctx.fillStyle = 'rgba(255, 255, 255, 0.1)'
roundRect(ctx, x, y, statWidth, statHeight, 15)
ctx.fill()
// 数值
ctx.fillStyle = '#ffffff'
ctx.font = 'bold 24px Arial'
ctx.textAlign = 'center'
ctx.fillText(stat.value.toString(), x + statWidth / 2, y + statHeight * 0.4)
// 标签
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'
ctx.font = '12px Arial'
ctx.fillText(stat.label, x + statWidth / 2, y + statHeight * 0.7)
})
// 励志语句
ctx.textAlign = 'center'
ctx.fillStyle = '#ffffff'
ctx.font = 'italic 20px Arial'
ctx.fillText('Keep going, never give up!', width / 2, height * 0.45)
ctx.font = '16px Arial'
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'
ctx.fillText('坚持就是胜利', width / 2, height * 0.5)
// 底部品牌信息
const bottomY = height * 0.65
const brandX = width * 0.1
ctx.textAlign = 'left'
ctx.fillStyle = '#ffffff'
ctx.font = 'bold 20px Arial'
ctx.fillText('Type Words', brandX, bottomY)
ctx.font = '12px Arial'
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'
ctx.fillText('词文记 - 高效英语学习', brandX, bottomY + 20)
ctx.fillText(window.location.origin, brandX, bottomY + 35)
// 二维码区域
const qrX = width * 0.75
const qrY = bottomY - 10
// 二维码背景
ctx.fillStyle = '#ffffff'
roundRect(ctx, qrX - 5, qrY - 5, 50, 50, 5)
ctx.fill()
// 绘制简单二维码
ctx.fillStyle = '#000000'
const moduleSize = 2
for (let row = 0; row < 20; row++) {
for (let col = 0; col < 20; col++) {
if (Math.random() > 0.5) {
ctx.fillRect(qrX + col * moduleSize, qrY + row * moduleSize, moduleSize, moduleSize)
}
}
}
// 将canvas转换为图片
const imageUrl = canvas.toDataURL('image/png', 1.0)
generatedImageUrl = imageUrl
} catch (error) {
console.error('生成图片失败:', error)
alert('生成图片失败,请重试')
} finally {
isGeneratingImage = false
}
}
// 复制图片到剪贴板
async function copyImageToClipboard() {
if (!generatedImageUrl) return
try {
const response = await fetch(generatedImageUrl)
const blob = await response.blob()
if (navigator.clipboard && window.ClipboardItem) {
await navigator.clipboard.write([
new ClipboardItem({
'image/png': blob
})
])
Toast.success('图片已复制到剪贴板!')
} else {
// 降级方案:下载图片
downloadImage()
}
} catch (error) {
console.error('复制失败:', error)
// 降级方案:下载图片
downloadImage()
}
}
// 下载图片
function downloadImage() {
if (!generatedImageUrl) return
const link = document.createElement('a')
link.download = `${APP_NAME} 分享_${studyStats.date}_${studyStats.dictionary}.png`
link.href = generatedImageUrl
link.click()
}
// 切换背景
function changeBackground() {
// 这里可以实现背景切换逻辑
console.log('切换背景')
}
// 绘制圆角矩形辅助函数
function roundRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number) {
ctx.beginPath()
ctx.moveTo(x + radius, y)
ctx.lineTo(x + width - radius, y)
ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
ctx.lineTo(x + width, y + height - radius)
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)
ctx.lineTo(x + radius, y + height)
ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
ctx.lineTo(x, y + radius)
ctx.quadraticCurveTo(x, y, x + radius, y)
ctx.closePath()
}
onMounted(generateShareImage)
</script>
<template>
<div class="flex-col center gap-1">
<BaseIcon>
<IconFluentShare20Regular/>
<!-- 分享学习总结按钮 -->
<BaseIcon @click="showShareImageDialog = true"
class="cursor-pointer hover:scale-110 transition-transform duration-200">
<IconFluentShare20Regular class="text-blue-500 hover:text-blue-600"/>
</BaseIcon>
<a
:href="GITHUB"
target="_blank"
rel="noreferrer"
aria-label="GITHUB 项目地址">
:href="GITHUB"
target="_blank"
rel="noreferrer"
aria-label="GITHUB 项目地址">
<BaseIcon>
<IconSimpleIconsGithub/>
</BaseIcon>
@@ -36,25 +288,178 @@ let showQQDialog = $ref(false)
</BaseIcon>
<a
href="https://x.com/typewords2"
target="_blank"
rel="noreferrer"
aria-label="关注我的 X 账户 typewords2">
href="https://x.com/typewords2"
target="_blank"
rel="noreferrer"
aria-label="关注我的 X 账户 typewords2">
<BaseIcon>
<IconRiTwitterFill class="color-blue"/>
</BaseIcon>
</a>
<a
href="mailto:zyronon@163.com"
target="_blank"
rel="noreferrer"
aria-label="发送邮件到 zyronon@163.com">
href="mailto:zyronon@163.com"
target="_blank"
rel="noreferrer"
aria-label="发送邮件到 zyronon@163.com">
<BaseIcon>
<IconMaterialSymbolsMail class="color-blue"/>
</BaseIcon>
</a>
</div>
<!-- 学习总结分享图片生成对话框 -->
<Dialog
title="分享"
:close-on-click-bg="true"
@close="generatedImageUrl = null"
custom-class="!max-w-4xl !w-auto">
<div class="flex min-w-160 max-w-200">
<!-- 左侧海报预览区域 -->
<div class="flex-1 p-6 border-r border-gray-200">
<!-- 生成中状态 -->
<div v-if="isGeneratingImage" class="relative">
<div class="w-80 h-104 bg-gradient-to-br from-gray-800 to-gray-900 rounded-xl p-6 text-white relative overflow-hidden">
<!-- 背景装饰 -->
<div class="absolute top-4 right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full"></div>
<div class="absolute bottom-8 left-8 w-12 h-12 bg-white bg-opacity-5 rounded-full"></div>
<!-- 加载状态 -->
<div class="flex items-center justify-center h-full">
<div class="text-center">
<div class="w-12 h-12 border-2 border-white border-t-transparent rounded-full animate-spin mx-auto mb-4"></div>
<div class="text-white text-sm">正在生成海报...</div>
</div>
</div>
</div>
</div>
<!-- 海报预览 -->
<div v-else-if="generatedImageUrl" class="relative">
<img
:src="generatedImageUrl"
alt="学习总结海报"
class="w-80 h-auto rounded-xl shadow-lg">
</div>
<!-- 默认预览状态 -->
<div v-else class="w-80 h-104 bg-gradient-to-br from-gray-800 to-gray-900 rounded-xl p-6 text-white relative overflow-hidden">
<!-- 背景装饰 -->
<div class="absolute top-4 right-4 w-16 h-16 bg-white bg-opacity-10 rounded-full"></div>
<div class="absolute bottom-8 left-8 w-12 h-12 bg-white bg-opacity-5 rounded-full"></div>
<!-- 顶部用户信息 -->
<div class="flex items-center mb-6">
<div class="w-12 h-12 bg-gray-600 rounded-full mr-3 flex items-center justify-center">
<IconSimpleIconsGithub class="w-6 h-6 text-white"/>
</div>
<div>
<div class="font-semibold text-lg">{{ baseStore.user?.name || '学习者' }}</div>
<div class="text-gray-300 text-sm">{{ dayjs().format('YYYY年MM月DD日') }}</div>
</div>
<div class="ml-auto text-xs text-gray-300">
Type Words | 英语学习
</div>
</div>
<!-- 统计数据 -->
<div class="grid grid-cols-3 gap-4 mb-8">
<div class="text-center">
<div class="text-2xl font-bold">{{ studyStats.total }}</div>
<div class="text-gray-300 text-xs">总词数</div>
</div>
<div class="text-center">
<div class="text-2xl font-bold">{{ studyStats.time }}</div>
<div class="text-gray-300 text-xs">学习时长</div>
</div>
<div class="text-center">
<div class="text-2xl font-bold">{{ studyStats.accuracy }}%</div>
<div class="text-gray-300 text-xs">正确率</div>
</div>
</div>
<!-- 励志语句 -->
<div class="text-center mb-8">
<div class="text-lg italic mb-2">Keep going, never give up!</div>
<div class="text-sm text-gray-300">坚持就是胜利</div>
</div>
<!-- 底部品牌信息 -->
<div class="absolute bottom-6 left-6 right-6">
<div class="flex justify-between items-end">
<div>
<div class="font-bold text-lg">Type Words</div>
<div class="text-xs text-gray-300">词文记 - 高效英语学习</div>
<div class="text-xs text-gray-400">{{ window.location.origin }}</div>
</div>
<div class="w-16 h-16 bg-white rounded p-2">
<div class="w-full h-full bg-black grid grid-cols-8 gap-0.5">
<div v-for="i in 64" :key="i" :class="Math.random() > 0.5 ? 'bg-black' : 'bg-white'"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧分享引导区域 -->
<div class="flex-1 p-8 pt-0 space-y-6">
<div class="mb-8">
<h2 class="text-2xl font-bold text-gray-800 mb-4 flex items-center">
<span class="mr-2">🎯</span>
分享你的进步
</h2>
<div class="">
<div class="flex items-start">
<span class="mr-2">🚀</span>
{{ APP_NAME }}学习英语也能成为超酷的事情
</div>
<div class="flex items-start">
<span class="mr-2">📸</span>
快来分享你的学习图片让你的进步刷屏朋友圈成为最受瞩目的英语学霸😎
</div>
<div class="flex items-start">
<span class="mr-2">💪</span>
这不只是简单的打卡更是你秀出英语实力的舞台
</div>
<div class="flex items-start">
<span class="mr-2">🔥</span>
分享你的战绩收获朋友们的点赞和认可让你的朋友圈也掀起一股英语学习的热潮
</div>
</div>
</div>
<!-- 个性化装扮 -->
<div
class="flex items-center justify-between px-6 py-3 bg-gray-200 rounded-lg cp hover:bg-gray-100 transition-all duration-200">
<div
@click="changeBackground"
class="flex items-center gap-2">
<IconMdiSparkles class="w-4 h-4 text-yellow-500"/>
换个背景
</div>
<span class="text-sm text-gray-500 bg-gray-100 px-2 py-1 rounded-full">随心装扮</span>
</div>
<!-- 分享战绩 -->
<div
@click="copyImageToClipboard"
class="flex items-center justify-start gap-space px-6 py-3 bg-gradient-to-r from-green-500 to-green-600 text-white cp rounded-lg hover:from-green-600 hover:to-green-700 transition-all duration-200">
<IconFluentCopy20Regular class="w-5 h-5"/>
<span class="font-medium">复制到剪贴板</span>
</div>
<div
@click="downloadImage"
class="flex items-center justify-start gap-space px-6 py-3 bg-gradient-to-r from-purple-500 to-purple-600 text-white cp rounded-lg hover:from-purple-600 hover:to-purple-700 transition-all duration-200">
<IconFluentArrowDownload20Regular class="w-5 h-5"/>
<span class="font-medium">保存高清海报</span>
</div>
</div>
</div>
</Dialog>
<Dialog v-model="showWechatDialog" title="Type Words 交流群">
<div class="w-120 p-6 pt-0">
<div class="mb-4">
@@ -92,4 +497,13 @@ a {
color: unset;
}
</style>
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
</style>

View File

@@ -139,131 +139,133 @@ calcWeekList(); // 新增:计算本周学习记录
:keyboard="false"
:show-close="false"
class="statistics-modal">
<div class="p-8 pr-3 bg-white rounded-2xl gap-3 flex">
<div class="space-y-6">
<!-- Header Section -->
<div class="text-center relative">
<div
class="text-3xl font-bold mb-2 bg-gradient-to-r from-purple-500 to-purple-700 bg-clip-text text-transparent">
<template v-if="practiceTaskWords.shuffle.length">
🎯 随机复习完成
</template>
<template v-else>
🎉 今日任务完成
</template>
</div>
<p class="font-medium text-lg">{{ encouragementText }}</p>
<div class="p-8 pr-3 bg-white rounded-2xl space-y-6">
<!-- Header Section -->
<div class="text-center relative">
<div
class="text-3xl font-bold mb-2 bg-gradient-to-r from-purple-500 to-purple-700 bg-clip-text text-transparent">
<template v-if="practiceTaskWords.shuffle.length">
🎯 随机复习完成
</template>
<template v-else>
🎉 今日任务完成
</template>
</div>
<p class="font-medium text-lg">{{ encouragementText }}</p>
</div>
<!-- Main Stats Grid -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<!-- Study Time -->
<div class="item">
<IconFluentClock20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">学习时长</div>
<div class="text-xl font-bold text-gray-900">{{ formattedStudyTime }}</div>
</div>
<!-- Main Stats Grid -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<!-- Study Time -->
<div class="item">
<IconFluentClock20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">学习时长</div>
<div class="text-xl font-bold text-gray-900">{{ formattedStudyTime }}</div>
</div>
<!-- Accuracy Rate -->
<div class="item">
<IconFluentTarget20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">正确率</div>
<div class="text-xl font-bold text-gray-900 mb-2">{{ accuracyRate }}%</div>
<div class="w-full bg-gray-200 rounded-full h-1" v-if="false">
<div
class="h-1 rounded-full transition-all duration-300"
:class="{
<!-- Accuracy Rate -->
<div class="item">
<IconFluentTarget20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">正确率</div>
<div class="text-xl font-bold text-gray-900 mb-2">{{ accuracyRate }}%</div>
<div class="w-full bg-gray-200 rounded-full h-1" v-if="false">
<div
class="h-1 rounded-full transition-all duration-300"
:class="{
'bg-green-500': accuracyRate >= 95,
'bg-yellow-500': accuracyRate >= 85 && accuracyRate < 95,
'bg-red-500': accuracyRate < 85
}"
:style="{ width: accuracyRate + '%' }">
</div>
:style="{ width: accuracyRate + '%' }">
</div>
</div>
<!-- New Words -->
<div class="item">
<IconFluentSparkle20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">新词</div>
<div class="text-xl font-bold text-gray-900">{{ statStore.newWordNumber }}</div>
</div>
<!-- New Words -->
<div class="item">
<IconFluentBook20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">复习</div>
<div class="text-xl font-bold text-gray-900">{{ statStore.newWordNumber }}</div>
</div>
</div>
<!-- Weekly Progress -->
<div class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl p-2">
<div class="text-center mb-4">
<div class="text-xl font-semibold text-gray-900 mb-1">本周学习记录</div>
</div>
<div class="flex justify-between gap-4">
<div
<!-- New Words -->
<div class="item">
<IconFluentSparkle20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">新词</div>
<div class="text-xl font-bold text-gray-900">{{ statStore.newWordNumber }}</div>
</div>
<!-- New Words -->
<div class="item">
<IconFluentBook20Regular class="text-purple-500"/>
<div class="text-sm text-gray-600 mb-1 font-medium">复习</div>
<div class="text-xl font-bold text-gray-900">{{ statStore.reviewWordNumber + statStore.writeWordNumber }}</div>
</div>
</div>
<div class="w-full gap-3 flex">
<div class="space-y-6 flex-1">
<!-- Weekly Progress -->
<div class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl p-2">
<div class="text-center mb-4">
<div class="text-xl font-semibold text-gray-900 mb-1">本周学习记录</div>
</div>
<div class="flex justify-between gap-4">
<div
v-for="(item, i) in list"
:key="i"
class="flex-1 text-center px-2 py-3 rounded-lg"
:class="item ? 'bg-green-500 text-white shadow-lg' : 'bg-white text-gray-700'"
>
<div class="font-semibold mb-1">{{ i + 1 }}</div>
<div class="w-2 h-2 rounded-full mx-auto mb-1"
:class="item ? 'bg-white bg-opacity-30' : 'bg-gray-300'"></div>
>
<div class="font-semibold mb-1">{{ i + 1 }}</div>
<div class="w-2 h-2 rounded-full mx-auto mb-1"
:class="item ? 'bg-white bg-opacity-30' : 'bg-gray-300'"></div>
</div>
</div>
</div>
<!-- Progress Overview -->
<div class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl py-2 px-6">
<div class="flex justify-between items-center mb-3">
<div class="text-xl font-semibold text-gray-900">学习进度</div>
<div class="text-2xl font-bold text-purple-600">{{ studyProgress }}%</div>
</div>
<Progress :percentage="studyProgress" size="large" :show-text="false"/>
<div class="flex justify-between text-sm text-gray-600 font-medium mt-4">
<span>已学习: {{ store.sdict.lastLearnIndex }}</span>
<span>总词数: {{ store.sdict.length }}</span>
</div>
</div>
</div>
<!-- Progress Overview -->
<div class="bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl py-2 px-6">
<div class="flex justify-between items-center mb-3">
<div class="text-xl font-semibold text-gray-900">学习进度</div>
<div class="text-2xl font-bold text-purple-600">{{ studyProgress }}%</div>
<ChannelIcons/>
</div>
<!-- Action Buttons -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
<BaseButton
:keyboard="settingStore.shortcutKeyMap[ShortcutKey.RepeatChapter]"
@click="options(EventKey.repeatStudy)">
<div class="center gap-2">
<IconFluentArrowClockwise20Regular/>
重学一遍
</div>
<Progress :percentage="studyProgress" size="large" :show-text="false"/>
<div class="flex justify-between text-sm text-gray-600 font-medium mt-4">
<span>已学习: {{ store.sdict.lastLearnIndex }}</span>
<span>总词数: {{ store.sdict.length }}</span>
</div>
</div>
<!-- Action Buttons -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
<BaseButton
:keyboard="settingStore.shortcutKeyMap[ShortcutKey.RepeatChapter]"
@click="options(EventKey.repeatStudy)">
<div class="center gap-2">
<IconFluentArrowClockwise20Regular/>
重学一遍
</div>
</BaseButton>
<BaseButton
:keyboard="settingStore.shortcutKeyMap[ShortcutKey.NextChapter]"
@click="options(EventKey.continueStudy)"
class="flex items-center justify-center gap-2 py-3 px-4 rounded-xl font-medium transition-all duration-300 hover:-translate-y-1 hover:shadow-lg"
:class="dictIsEnd ? 'bg-gradient-to-r from-purple-500 to-purple-600 text-white' : 'bg-gradient-to-r from-green-500 to-green-600 text-white'">
</BaseButton>
<BaseButton
:keyboard="settingStore.shortcutKeyMap[ShortcutKey.NextChapter]"
@click="options(EventKey.continueStudy)">
<div class="center gap-2">
<IconFluentPlay20Regular/>
{{ dictIsEnd ? '从头开始练习' : '再来一组' }}
</BaseButton>
<BaseButton
: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/>
返回主页
</div>
</BaseButton>
</div>
</div>
</BaseButton>
<BaseButton
: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/>
返回主页
</div>
</BaseButton>
</div>
<ChannelIcons/>
</div>
</Dialog>
</template>