feat: 优化随机刷题模式和进度显示

功能改进:
- 随机模式下已答题目不再重复出现
- 所有题目回答完成后显示总结页面
- 进度显示从"题号/总数"改为"已答数/总数"

UI修复:
- 修复小屏幕下悬浮球进度环错位问题
- 使用 SVG viewBox 实现自适应缩放
- 新增超小屏幕(≤380px)优化

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
yanlongqi 2025-11-10 11:16:46 +08:00
parent c50cf9ee7b
commit aaf1b78f3f
3 changed files with 61 additions and 15 deletions

View File

@ -93,8 +93,8 @@
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 64px; width: 100%;
height: 64px; height: 100%;
transform: rotate(-90deg); transform: rotate(-90deg);
pointer-events: none; pointer-events: none;
} }
@ -135,8 +135,9 @@
.statsCard { .statsCard {
padding: 6px 12px; padding: 6px 12px;
gap: 10px; gap: 8px;
border-radius: 10px; border-radius: 10px;
font-size: 12px;
} }
.statsLabel { .statsLabel {
@ -144,11 +145,11 @@
} }
.statsValue { .statsValue {
font-size: 14px; font-size: 13px;
} }
.statsDivider { .statsDivider {
height: 18px; height: 16px;
} }
.floatButton { .floatButton {
@ -156,13 +157,43 @@
height: 58px; height: 58px;
} }
.progressRing { .icon {
width: 58px; font-size: 22px;
height: 58px; }
}
// 超小屏幕优化
@media (max-width: 380px) {
.floatButtonWrapper {
right: 12px;
bottom: 75px;
}
.statsCard {
padding: 5px 10px;
gap: 6px;
border-radius: 8px;
}
.statsLabel {
font-size: 9px;
}
.statsValue {
font-size: 12px;
}
.statsDivider {
height: 14px;
}
.floatButton {
width: 54px;
height: 54px;
} }
.icon { .icon {
font-size: 22px; font-size: 20px;
} }
} }

View File

@ -32,7 +32,7 @@ const QuestionFloatButton: React.FC<QuestionFloatButtonProps> = ({
<div className={styles.statsRow}> <div className={styles.statsRow}>
<span className={styles.statsLabel}></span> <span className={styles.statsLabel}></span>
<span className={styles.statsValue}> <span className={styles.statsValue}>
{currentIndex + 1}/{totalQuestions} {answeredCount}/{totalQuestions}
</span> </span>
</div> </div>
<div className={styles.statsDivider} /> <div className={styles.statsDivider} />
@ -54,7 +54,7 @@ const QuestionFloatButton: React.FC<QuestionFloatButtonProps> = ({
{/* 悬浮球 */} {/* 悬浮球 */}
<div className={styles.floatButton} onClick={onClick}> <div className={styles.floatButton} onClick={onClick}>
{/* 进度环 */} {/* 进度环 */}
<svg className={styles.progressRing} width="64" height="64"> <svg className={styles.progressRing} viewBox="0 0 64 64">
<circle <circle
className={styles.progressRingCircle} className={styles.progressRingCircle}
strokeWidth="3" strokeWidth="3"

View File

@ -303,10 +303,25 @@ const QuestionPage: React.FC = () => {
// 随机模式:从题库中随机选择一题 // 随机模式:从题库中随机选择一题
if (randomMode) { if (randomMode) {
// 生成一个不等于当前索引的随机索引 // 获取所有未答题目的索引
do { const unansweredIndexes: number[] = [];
nextIndex = Math.floor(Math.random() * allQuestions.length); for (let i = 0; i < allQuestions.length; i++) {
} while (nextIndex === currentIndex && allQuestions.length > 1); if (!answeredStatus.has(i)) {
unansweredIndexes.push(i);
}
}
// 如果所有题目都已回答,显示总结页面
if (unansweredIndexes.length === 0) {
setShowSummary(true);
// 清除进度
localStorage.removeItem(getStorageKey());
return;
}
// 从未答题目中随机选择一题
const randomIdx = Math.floor(Math.random() * unansweredIndexes.length);
nextIndex = unansweredIndexes[randomIdx];
} else { } else {
// 顺序模式:检查是否完成所有题目 // 顺序模式:检查是否完成所有题目
if (currentIndex + 1 >= allQuestions.length) { if (currentIndex + 1 >= allQuestions.length) {