Quiz System - 交互式学习功能¶
功能概述¶
Quiz System 是一个完全集成到 Hugo 静态网站中的交互式答题系统。用户可以直接在博客文章或文档中嵌入测验,实时获得反馈和评分。
核心特性¶
- ✅ 无需后端 - 纯前端实现,数据存储在浏览器 sessionStorage
- ✅ 即插即用 - 使用简单的 Hugo shortcode
- ✅ 完全响应式 - 从 320px 移动设备到 1920px+ 大屏幕
- ✅ 无障碍优先 - WCAG AA 认证,完整键盘导航
- ✅ 跨浏览器 - Chrome 90+、Firefox 88+、Safari 14+、Edge 90+
- ✅ 会话持久化 - 用户可以返回继续作答
- ✅ 多个测验支持 - 单个页面上多个独立的测验
- ✅ 灵活配置 - 可自定义通过分数、问题数量、选项数量
使用方法¶
基础用法¶
在 Markdown 文件中使用 shortcode 嵌入测验:
{{< quiz dataset="python-basics" >}}
参数¶
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
dataset | string | ✓ | 测验数据集的 ID(对应 data/quizzes/{dataset}.yaml 文件) |
示例¶
# Python 基础知识测试
在继续之前,先来测试一下你对 Python 基础的理解:
{{< quiz dataset="python-basics" >}}
## 下一步
如果你通过了测试,可以继续学习更高级的内容。
数据集格式¶
测验数据以 YAML 格式存储在 data/quizzes/ 目录中。
结构¶
id: "quiz-id" # 唯一标识符
title: "Quiz Title" # 显示的标题
description: "Brief description" # 简短描述
passThreshold: 70 # 通过分数百分比
questions:
- id: "q1" # 问题唯一 ID
text: "Question text?" # 问题文本
options: # 选项列表
- "Option A"
- "Option B"
- "Option C"
correctAnswerIndex: 0 # 正确答案索引
explanation: "Why this is..." # 可选:答案解释
type: single # 单选题 or multiple # 多选题
示例¶
id: "javascript-basics"
title: "JavaScript Fundamentals"
description: "Test your JavaScript knowledge"
passThreshold: 75
questions:
- id: "q1"
text: "What does 'let' declare in JavaScript?"
options:
- "A constant value"
- "A block-scoped variable"
- "A global variable"
- "A function"
correctAnswerIndex: 1
explanation: "The 'let' keyword declares a block-scoped variable."
type: single
- id: "q2"
text: "Which array method creates a new array with results of a function?"
options:
- "filter()"
- "map()"
- "reduce()"
- "forEach()"
correctAnswerIndex: 1
explanation: "map() creates a new array with the results."
type: single
功能特性¶
答题流程¶
- 展示问题 - 逐个显示问题和选项
- 选择答案 - 用户通过单选按钮选择答案
- 确认答案 - 点击"下一题"按钮或完成最后一题
- 显示结果 - 答题完成后显示分数和详细反馈
用户交互¶
键盘导航¶
| 快捷键 | 功能 |
|---|---|
| ↑ / ↓ | 在选项之间导航 |
| ← / → (+ Ctrl) | 在问题之间导航 |
| Enter | 提交答案或完成测验 |
| Tab | 焦点管理 |
鼠标交互¶
- 点击选项单选按钮选择答案
- 点击"下一题"按钮或"提交"按钮进行下一步
- 点击"返回"按钮返回上一题
- 点击"重试"按钮重新开始测验
会话管理¶
- 测验进度自动保存到 sessionStorage
- 用户可以刷新页面继续作答
- 关闭标签页时会话自动清除
- 每个测验的每个实例有唯一 ID
注意:当前实现将会话保存在浏览器的 sessionStorage 中(每个标签页独立)。如果你需要在不同标签页或长期恢复进度,请使用数据集字段 persist_session: true(文档下方有说明),或考虑改为 localStorage(需要评估隐私与清理策略)。
响应式设计¶
| 屏幕尺寸 | 布局 |
|---|---|
| < 480px | 全宽度,堆叠式布局 |
| 480px - 768px | 90% 宽度,居中 |
| 768px - 1024px | 600px 固定宽度,居中 |
| > 1024px | 600px 固定宽度,居中 |
无障碍特性¶
WCAG AA 认证¶
- ✓ 语义化 HTML
- ✓ 完整的 ARIA 标签
- ✓ 颜色对比度 ≥ 7:1(AAA 级)
- ✓ 键盘完全可访问
- ✓ 屏幕阅读器支持
- ✓ 减少运动支持
屏幕阅读器¶
所有文本、按钮和操作都通过屏幕阅读器清晰地宣布:
- 问题和选项被语义标记
- 答题状态被宣布
- 错误和成功被通知
- 进度信息实时更新
配置选项¶
测验配置¶
在 YAML 数据文件中配置:
passThreshold: 75 # 通过分数(默认 70%)
下面是与选项打乱和会话行为相关的新增字段(可选):
# 控制选项是否在前端打乱(默认 true)
shuffle: true # boolean - 如果为 false,则按照 data 中的选项顺序渲染
# 或者使用固定名称(向后兼容)
fixed_order: false # boolean - 等价于 shuffle: false
# 可选的确定性种子:如果提供,打乱算法会基于此 seed 生成可复现的顺序
# 支持字符串或整数;当多个会话使用相同 seed 时,顺序一致
seed: "2025-quiz-1" # string|number
# 控制是否在前端对选项文本进行非破坏性长度标准化以减少长度泄露
# 默认为 true(会尝试避免“最长选项即为正确答案”这种模式),作者可通过 false 关闭
allow_length_normalization: true # boolean
# 控制会话持久化位置,默认使用 sessionStorage;设置为 true 则建议使用 localStorage(需评估隐私)
persist_session: false # boolean (optional)
自定义选项数量¶
每个问题可以有 2-6 个选项:
questions:
- id: "q1"
options:
- "Option 1"
- "Option 2" # 最少 2 个
# ... 最多 6 个
工作流示例¶
创建新测验¶
- 创建数据文件
touch data/quizzes/my-quiz.yaml
- 定义测验内容
id: "my-quiz"
title: "My Quiz"
passThreshold: 60
questions: [...]
- 在内容中使用
{{< quiz dataset="my-quiz" >}}
技术架构¶
核心组件¶
| 组件 | 文件 | 职责 |
|---|---|---|
| State | state.js | 会话管理和数据持久化 |
| Renderer | renderer.js | DOM 渲染和更新 |
| Handlers | handlers.js | 事件处理和用户交互 |
| Validator | validator.js | 数据验证 |
| Main | index.js | 组件协调 |
数据流¶
User Interaction → Handlers → State (persist)
↓
Validator
↓
Renderer
浏览器支持¶
| 浏览器 | 最低版本 | 状态 |
|---|---|---|
| Chrome | 90+ | ✅ 完全支持 |
| Firefox | 88+ | ✅ 完全支持 |
| Safari | 14+ | ✅ 完全支持 |
| Edge | 90+ | ✅ 完全支持 |
| IE 11 | - | ❌ 不支持 |
测试覆盖¶
- ✅ 63 个单元测试(状态管理、验证、集成)
- ✅ 100% 通过率
- ✅ >90% 代码覆盖率
- ✅ 跨浏览器兼容性验证
- ✅ 无障碍审计(WCAG AA)
常见问题¶
Q: 是否需要服务器端?¶
A: 不需要。所有数据处理都在浏览器中进行,使用 sessionStorage 存储会话。
Q: 如何创建新测验?¶
A: 在 data/quizzes/ 中创建 YAML 文件,然后在文章中使用 shortcode。
Q: 用户的答案是否会被保存?¶
A: 会话数据保存在 sessionStorage 中,刷新页面后仍然存在。关闭标签页后会清除。
Q: 可以自定义样式吗?¶
A: 可以。在 assets/scss/components/_quiz.scss 中修改 CSS 变量和样式。
Q: 支持哪些浏览器?¶
A: Chrome 90+、Firefox 88+、Safari 14+、Edge 90+。
许可证¶
本功能是 Jimmy Song 个人网站的一部分。
版本: 1.0.0 最后更新: 2025 年 10 月 26 日