☰
【OpenHarmony/HarmonyOs 】错题本功能从 0 到 1:答题记录、去重收录与复习闭环
2026/10/18 5:18:00 网站建设 项目流程

【OpenHarmony/HarmonyOs 】错题本功能从 0 到 1:答题记录、去重收录与复习闭环

错题本是学习 App 里非常实用的功能。用户不是只需要“做题”,更需要知道自己错在哪里、后面怎么复习。本文结合我的「化学视界」项目,记录我是如何开发错题本功能的。📝

一、为什么要做错题本?

化学学习有大量记忆和理解内容,比如元素性质、方程式现象、实验操作、有机化学概念等。用户答错题后,如果没有复习入口,很容易“错过就忘”。

所以我在挑战模块里加入了错题本:

  • 答错时自动收录。
  • 答对后可以移除。
  • 错题列表可反复练习。
  • 设置页能看到错题数量。
  • 用户可以清空错题。

这让题库不只是一次性练习,而是形成“做题 → 出错 → 复习 → 掌握”的闭环。

二、错题本的数据应该怎么存?

我没有保存完整题目内容,而是只保存题目 id:

const STORAGE_KEY='quiz_wrong_question_ids';

原因很简单:题库本身已经在本地数据中,错题本只需要记录“哪些题错过”。这样数据更轻,也避免重复保存题干、选项和解析。

读取逻辑如下:

functionreadIds():number[] {try{constraw =AppStorage.get<string>(STORAGE_KEY);if(!raw || raw.length===0) {return[]; }constparsed =JSON.parse(raw)asnumber[];if(!Array.isArray(parsed)) {return[]; }returnparsed.filter((n:number) =>typeofn ==='number'); }catch{return[]; } }

这里做了容错处理:如果本地数据为空、格式异常或解析失败,就返回空数组,避免页面崩掉。

三、答错时自动加入错题集

加入错题时要去重,否则用户同一道题答错多次,错题本会出现重复项:

exportfunctionaddWrongQuestionId(id:number): void { const ids = readIds();if(!ids.includes(id)) { ids.push(id); writeIds(ids); } }

这个逻辑虽然简单,但很关键。错题本应该反映“哪些题没掌握”,而不是“错了多少次”。如果要统计错误次数,可以额外做字段,但不应该让列表重复。

四、答对后移除错题

当用户在错题复习里答对某道题后,可以从错题集中移除:

exportfunctionremoveWrongQuestionId(id:number):void{writeIds(readIds().filter((x:number) =>x !== id)); }

我开发时把“移除”设计为明确动作:只有复习答对后才移除,而不是用户随便进入题目就清掉。这样更符合学习逻辑。

五、把错题 id 还原成完整题目

错题页面展示时,需要根据 id 找回完整题目:

exportfunctiongetWrongQuestions():QuizQuestion[] {constlist:QuizQuestion[] = [];readIds().forEach((id: number) =>{constq = quizData.find((x: QuizQuestion) =>x.id=== id);if(q) { list.push(q); } });returnlist; }

这里没有直接map,而是手动判断q是否存在。这样即使后续题库调整,某个旧 id 找不到,也不会影响整个错题本。

六、挑战页中的错题状态

在QuizView中,我为错题模式单独维护了一组状态:

@StatewrongQuestions: QuizQuestion[] = [];@StatewrongIndex: number =0;@StatewrongAnswer: string ='';@StatewrongAnswered: boolean = false;@StatewrongCorrect: boolean = false;@StatewrongResultAppear: boolean = false;@StateexplanationWrongQ: QuizQuestion | null = null;

为什么不复用练习模式的状态?因为错题模式有自己的特殊逻辑:

  • 答对后可能移除当前题。
  • 移除后列表长度会变化。
  • 解析区仍然要展示刚答过的题。
  • 当前索引需要防止越界。

所以我把错题模式独立出来,避免和普通练习互相影响。

七、防止答对后列表错位

项目里有一个很细的状态:

@StateexplanationWrongQ: QuizQuestion |null=null;

它的作用是固定展示刚作答的那道题。因为如果用户答对后,这道题会从错题列表移除,列表索引可能变化。如果解析区直接依赖wrongQuestions[wrongIndex],就可能显示到下一道题。

这是我开发错题本时遇到的一个真实问题:数据变化后 UI 绑定对象也跟着变了。解决办法就是把“当前解析题”单独保存一份。

八、设置页展示错题数量

错题本不只在挑战页出现,设置页也会展示入口和数量:

loadBadge() {this.wrongCount = getWrongQuestions().length;constfavs = getAllFavorites();this.favoriteCount = favs.length;this.unlockCount =this.achievementManager.getUnlockedCount(); }

设置项中展示徽标:

{icon:'📚',title:'我的错题',subtitle:'答错的题目自动收录',action:'wrongbook',badge: this.wrongCount >0? String(this.wrongCount) :'',badgeColor:'#F44336'}

这样用户不用进入挑战页,也能知道自己有没有待复习内容。

九、清空错题:给用户数据控制权

设置页中提供了清空错题的逻辑:

handleClearConfirm() {if(this.clearActionType ==='wrong') { clearWrongBook();this.wrongCount =0; }else{ clearFavorites();this.favoriteCount =0; }this.showClearConfirm =false; }

学习数据应该由用户控制。错题本是帮助复习的工具,不应该变成无法清理的负担。

十、错题本和收藏夹的区别

开发时我也思考过一个问题:错题本和收藏夹都能保存内容,它们有什么区别?

我的理解是:

  • 收藏夹是用户主动选择的内容。
  • 错题本是系统根据学习结果自动生成的内容。

所以收藏夹更像“我觉得重要”,错题本更像“我还没掌握”。这两个入口在学习闭环里承担的角色不同,不能混在一起。

收藏夹适合放:

  • 常查元素。
  • 重点方程式。
  • 重要知识点。

错题本适合放:

  • 答错的题目。
  • 需要反复练习的知识点。
  • 用户短期薄弱内容。

正因为这个区别,我在代码里也把它们拆成两个工具类:收藏由FavoritesManager管理,错题由WrongBookStore管理。这样后续维护时不会互相影响。

十一、错题本后续可以怎么优化?

当前错题本已经实现了基础闭环,但还可以继续增强:

  • 给错题增加“错误次数”,区分偶然错误和高频错误。
  • 给错题增加“最近答错时间”,优先复习近期错题。
  • 按题目分类统计薄弱模块。
  • 在学习统计页展示错题趋势。
  • 根据错题自动推荐知识点。

不过我没有一开始就把这些都做进去,因为基础功能要先稳定。先保证收录、复习、移除、清空这些主流程可靠,再做增强会更稳。

十二、我开发错题本的总结

错题本的开发重点不在 UI,而在学习流程:

  • ❌ 答错自动收录。
  • ✅ 答对可以移除。
  • 🔁 支持反复复习。
  • 🧠 解析区固定当前题。
  • 🧹 支持用户清空。

从代码上看,错题本只保存 id,非常轻量;从体验上看,它把挑战模块从“做完就结束”变成了“持续复习”。这就是学习工具真正有价值的地方。🌱

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询