主要改进: - 新增题目导航抽屉组件,支持快速跳转到任意题目 - 新增悬浮球导航按钮,实时显示答题进度和统计信息 - 优化顶部导航栏,移除进度条,简化为返回、标题和设置三个按钮 - 将答题设置改为弹窗模式,提供更好的交互体验 - 优化题目列表卡片设计,减小高度使其更紧凑 - 题目列表显示题号、分类标签、题目内容和答题状态 - 支持答题进度持久化,刷新页面不丢失进度 技术细节: - 使用 Ant Design 的 Drawer、Modal、Tag 等组件 - 采用 CSS Modules 实现样式隔离 - 使用 LocalStorage 保存答题进度和设置 - 响应式设计,适配移动端和PC端 - 修复 TypeScript 编译错误 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import React from 'react'
|
|
import { UnorderedListOutlined } from '@ant-design/icons'
|
|
import styles from './QuestionFloatButton.module.less'
|
|
|
|
interface QuestionFloatButtonProps {
|
|
currentIndex: number
|
|
totalQuestions: number
|
|
onClick: () => void
|
|
correctCount: number
|
|
wrongCount: number
|
|
}
|
|
|
|
const QuestionFloatButton: React.FC<QuestionFloatButtonProps> = ({
|
|
currentIndex,
|
|
totalQuestions,
|
|
onClick,
|
|
correctCount,
|
|
wrongCount,
|
|
}) => {
|
|
if (totalQuestions === 0) return null
|
|
|
|
const answeredCount = correctCount + wrongCount
|
|
const progress = Math.round((answeredCount / totalQuestions) * 100)
|
|
|
|
const radius = 28.5
|
|
const circumference = 2 * Math.PI * radius
|
|
|
|
return (
|
|
<div className={styles.floatButtonWrapper}>
|
|
{/* 统计信息卡片 */}
|
|
<div className={styles.statsCard}>
|
|
<div className={styles.statsRow}>
|
|
<span className={styles.statsLabel}>进度</span>
|
|
<span className={styles.statsValue}>
|
|
{currentIndex + 1}/{totalQuestions}
|
|
</span>
|
|
</div>
|
|
<div className={styles.statsDivider} />
|
|
<div className={styles.statsRow}>
|
|
<span className={styles.statsLabel}>正确</span>
|
|
<span className={styles.statsValue} style={{ color: '#52c41a' }}>
|
|
{correctCount}
|
|
</span>
|
|
</div>
|
|
<div className={styles.statsDivider} />
|
|
<div className={styles.statsRow}>
|
|
<span className={styles.statsLabel}>错误</span>
|
|
<span className={styles.statsValue} style={{ color: '#ff4d4f' }}>
|
|
{wrongCount}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 悬浮球 */}
|
|
<div className={styles.floatButton} onClick={onClick}>
|
|
{/* 进度环 */}
|
|
<svg className={styles.progressRing} width="64" height="64">
|
|
<circle
|
|
className={styles.progressRingCircle}
|
|
strokeWidth="3"
|
|
fill="transparent"
|
|
r={radius}
|
|
cx="32"
|
|
cy="32"
|
|
/>
|
|
<circle
|
|
className={styles.progressRingCircleProgress}
|
|
strokeWidth="3"
|
|
fill="transparent"
|
|
r={radius}
|
|
cx="32"
|
|
cy="32"
|
|
style={{
|
|
strokeDasharray: `${circumference}`,
|
|
strokeDashoffset: `${circumference * (1 - progress / 100)}`,
|
|
}}
|
|
/>
|
|
</svg>
|
|
|
|
{/* 中心图标 */}
|
|
<div className={styles.floatButtonContent}>
|
|
<UnorderedListOutlined className={styles.icon} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default QuestionFloatButton
|