HarmonyOS APP<玩转React>开源教程二十四:错题本功能
第24次:错题本功能
这一篇我们继续沿着题库系统往下走,讲清楚
WrongAnswerService.ets和WrongAnswerBookPage.ets。错题本不是一个附属页面,而是题库闭环里非常关键的复习模块。
为什么错题本不能只是“存错题”
很多初学者做错题本时,只会把答错的题塞进一个数组里。这样当然也能跑,但很快就不够用了,因为真正的错题本还要解决这些问题:
- 同一道题多次答错时怎么处理
- 用户答对后能不能标记为已掌握
- 错题是否需要记录最后一次练习时间
- 列表应该按什么顺序展示
- 如何从错题本再次进入练习
当前项目的 WrongAnswerService 恰好把这些都考虑进去了。
一、错题记录为什么不是只存题目 ID
当前的错题记录 WrongAnswerRecord 会保存很多信息:
questionIdquestionuserAnswercorrectAnswerrecordedAtattemptCountisMasteredlastAttemptAt
这说明项目并不是把错题本当成一个简单收藏夹,而是把它当成一个“复习跟踪器”。
尤其是这几个字段很关键:
attemptCount:能看出这道题卡了用户几次。isMastered:能看出这道题是不是已经会了。lastAttemptAt:能帮助后续做复习排序或复盘分析。
这也提醒我们:错题本真正有价值的,不只是“错过”,而是“后续怎么复习”。
二、为什么 addWrongAnswer() 要支持更新旧记录
如果用户第一次答错某道题,你当然要新增记录;但如果用户后面又把同一道题答错一次,显然不应该再重复新增一条相同记录。
当前 addWrongAnswer() 的做法是:
- 先查有没有同题记录
- 如果有,就更新用户答案、尝试次数、最后练习时间,并把
isMastered重置为false - 如果没有,再新建记录
这种设计非常合理,因为它让一条错题记录真正对应“一道题的掌握过程”,而不是“答错的次数清单”。
三、为什么要区分“全部错题”和“未掌握错题”
WrongAnswerService 同时提供了:
getAllWrongAnswers()getUnmasteredWrongAnswers()getUnmasteredCount()
这说明服务层很明确地区分了两种视角:
全部错题
适合回顾历史。
未掌握错题
适合立即复习。
这个区分很重要,因为学习产品最怕的就是把所有历史错误都一股脑堆给用户。真正有效的复习,应该优先处理“还没掌握”的内容。
四、错题本页面为什么做成“列表 + 详情面板”
WrongAnswerBookPage 的页面结构很值得学:
- 顶部导航栏
- 统计条
- 开始练习错题按钮
- 错题列表
- 底部详情弹层
列表页只负责快速浏览,点击某条错题后再弹出详情面板,展示:
- 模块名
- 完整题干
- 所有选项
- 你的答案
- 正确答案
- 题目解析
- 移除按钮
这种设计很适合手机端。因为错题内容通常比较长,如果每条列表都展开,页面会非常乱;而用弹层展示详情,既保留了列表浏览效率,又保留了完整信息查看能力。
五、从错题本继续练习为什么是关键能力
错题本真正的价值,不在于“存起来”,而在于“继续练”。当前页面上的“开始练习错题”按钮会跳转到:
QuizPracticePage- 并携带
isFromWrongBook: true
随后 QuizPracticePage 会切换到错题练习模式,只读取未掌握错题集合。这就形成了一个非常完整的学习闭环:
- 做题
- 产生错题
- 进入错题本
- 再次练习
- 答对后标记已掌握
这种闭环一旦形成,题库系统才真正有“成长性”。
六、详情面板里为什么要同时高亮用户答案和正确答案
在 DetailPanel() 中,每个选项会根据状态展示不同背景:
- 正确答案:绿色风格
- 用户错误答案:红色风格
这种“答案对比式展示”比只告诉用户“你错了”更有效,因为它能帮助用户一眼看到:
- 我选错的是哪一项
- 正确答案到底是哪一项
这在复习场景里尤其重要。错题本页面不是考试现场,而是复盘现场,重点是帮助用户理解差距。
七、自己操作时最推荐的路径
- 从题库页进入练习。
- 故意答错几题。
- 回到题库页,进入错题本。
- 先看统计条和错题列表是否正确更新。
- 点击某道错题,打开详情面板查看解析。
- 再点击“开始练习错题”,看题目是否只来自未掌握集合。
- 如果在错题模式下答对,看它是否会被标记为已掌握。
这条路径跑通后,你就会非常清楚错题本在整个题库系统中的价值。
八、本篇常见坑
1. 每次答错都新增一条重复记录
这样错题本会越来越脏,不利于复习。
2. 错题答对后不更新掌握状态
没有 isMastered,错题本就无法形成复习闭环。
3. 错题列表不做排序
当前项目按时间倒序展示,更符合最近复习场景。
4. 错题本只能看,不能练
那它就只是“历史记录”,不是“学习工具”。
本篇小结
这一篇最重要的理解是:错题本不是题库的附件,而是题库系统的第二增长曲线。它把一次答错,变成了后续复习和最终掌握的机会。
当前项目的做法很值得借鉴:
- 服务层记录错题与掌握状态
- 页面层做浏览、查看、移除和再练习
- 与题库练习页通过参数模式打通
这就是一个完整、实用的错题本设计。
跟着真实源码继续往下看
错题记录新增或更新的真实代码如下:
static async addWrongAnswer(question: InterviewQuestion, userAnswer: number): Promise<void> {
const existingIndex = WrongAnswerService.wrongAnswers.findIndex(
r => r.questionId === question.id
);
const now = new Date().toISOString();
if (existingIndex >= 0) {
const existing = WrongAnswerService.wrongAnswers[existingIndex];
existing.userAnswer = userAnswer;
existing.attemptCount += 1;
existing.lastAttemptAt = now;
existing.isMastered = false;
}
}
错题本页从错题列表进入练习的真实代码如下:
Button() {
Row() {
Text('📝')
Text('开始练习错题')
}
}
.onClick(() => {
router.pushUrl({
url: 'pages/QuizPracticePage',
params: { isFromWrongBook: true }
});
})
按这个顺序动手
- 打开
WrongAnswerService.ets,看addWrongAnswer和markAsMastered。 - 再打开
WrongAnswerBookPage.ets,搜索isFromWrongBook。 - 最后去
QuizPracticePage.ets看这个参数如何切换题目来源。
课后练习
- 思考如果你要增加“按模块筛选错题”,服务层和页面层分别要改哪里。
- 观察
WrongAnswerService为什么要记录lastAttemptAt,想一想它未来还能支持哪些排序方式。 - 设想一个“只练最近 7 天的错题”功能,写出你会新增的过滤逻辑。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)