【OpenHarmony/HarmonyOs 】化学题库挑战模块实践每日一题、练习模式与限时挑战「化学视界」不是只提供资料查询也提供题库挑战功能。用户可以做每日题、普通练习、限时挑战也可以复习错题。本文记录我是如何开发挑战模块的。一、挑战模块的定位学习 App 只看资料是不够的。化学知识需要通过练习巩固所以我给项目设计了挑战模块。挑战模块包含四个入口⏱️ 限时挑战。 每日一题。✍️ 练习模式。 错题复习。这四个入口对应不同学习场景限时挑战训练速度和掌握程度。每日一题保持学习习惯。练习模式按难度和分类刷题。错题复习针对薄弱点补强。二、题目模型设计题目数据中包含题干、选项、答案、解析、分类和难度。页面展示时可以根据这些字段决定标签、颜色和筛选条件。挑战页中常用状态如下StateselectedTab: number 0;StateselectedLevel:all|middle|highall;StateselectedDifficulty:all|easy|medium|hardall;StatedailyQuestion: QuizQuestion | null null;StateselectedAnswer: string ;StateisAnswered: boolean false;StateisCorrect: boolean false;我把不同模式的状态拆开维护虽然字段看起来多但逻辑更清楚。三、每日一题按日期同步题目每日一题的关键是同一天保持同一道官方题跨天自动刷新。项目中的同步逻辑如下syncDailyForCalendarDay():void{consttoday newDate();constmo today.getMonth() 1;constda today.getDate();constdateKey ${today.getFullYear()}-${mo 10?0 mo : mo}-${da 10?0 da : da};constofficial getDailyQuestion();if(dateKey !this.lastDailyCalendarKey) {this.lastDailyCalendarKey dateKey;this.dailyQuestion official;this.currentDailyId official.id;this.viewingOfficialDailytrue;this.isAnsweredfalse;this.selectedAnswer; } }我开发这个功能时重点处理的是“同一天内不要反复重置用户状态”。如果用户已经换了一题或已经作答页面刷新时不应该突然覆盖。四、练习模式筛选题目池再打乱练习模式支持按学段和难度筛选loadPracticeQuestions() { let pool: QuizQuestion[] [];if(this.selectedLevel all) { pool quizData.slice(); }else{ pool getQuestionsByLevel(this.selectedLevel); }if(this.selectedDifficulty !all) { pool pool.filter((q: QuizQuestion) q.difficulty this.selectedDifficulty); }this.shuffleArray(pool);this.practiceQuestions pool;this.currentPracticeIndex 0; }这里的开发思路是先根据学段选题。再根据难度过滤。最后打乱顺序。每次切换条件都重置当前进度。五、洗牌算法避免每次都是同样顺序题目打乱使用常见的交换方式shuffleArray(arr: QuizQuestion[]) {for(leti arr.length-1; i 0; i--) {constj Math.floor(Math.random() * (i 1));consttemp arr[i]; arr[i] arr[j]; arr[j] temp; } }这样用户每次进入练习时题目顺序都不一样减少机械背答案的情况。六、限时挑战设置、答题、结果三阶段限时挑战页面中我把挑战状态分成三种StateprivatechallengeState: string setup;StateprivatequestionCount: number 10;StateprivatetimePerQuestion: number 60;Stateprivatequestions: QuizQuestion[] [];StateprivatecurrentIndex: number 0;StateprivateremainingSeconds: number 0;三个阶段分别是setup设置题目数量、分类、时间。playing正在答题。result展示答题结果。这样的状态机结构比用一堆布尔值更清晰。七、挑战设置用户自己控制难度限时挑战允许用户选择学段。知识分类。题目数量。每题时间。时间选项定义如下privatetimeOptions: TimeOption[] [ { value:0,name:不限}, { value:30,name:30秒}, { value:60,name:1分钟}, { value:90,name:1分半} ];我没有强制所有用户都限时因为学习阶段不同。有些用户想练速度有些用户只是想慢慢复习。八、题目标签让用户知道自己在做什么挑战页中我写了一个题号展示函数getQuestionChipText(question:QuizQuestion,mode:number):string{if(mode 1) {return第${this.currentPracticeIndex 1}题; }if(mode 2) {return错题${this.wrongIndex 1}/${this.wrongQuestions.length}; }return(this.viewingOfficialDaily?今日题目:随机练习) · #${question.id}; }这个细节能让用户明确当前模式是在做每日题、练习题还是错题复习。九、答题反馈正确和错误都要有解释挑战模块里用户提交答案后不会只显示“对/错”还会展示解析。学习类 App 的重点不是判分而是帮助用户理解。因此我设计答题流程时把“结果状态”和“解析展示”放在一起未作答展示选项和提交按钮。已作答展示正确答案、用户答案、解析。答错加入错题本。答对错题可以从错题本移除。十、挑战模块和成就系统的联动挑战模块不是孤立功能。用户答题之后成就系统也会记录行为recordQuizAnswer(correct: boolean, quizId: string): void {if(correct) {this.statistics.dailyQuizCorrect 1;this.checkAndUnlock(quiz_correct_5,this.statistics.dailyQuizCorrect);this.checkAndUnlock(quiz_correct_20,this.statistics.dailyQuizCorrect); }this.scheduleSave(); }这样用户做题不只是得到当前分数还会转化成长期成就。我开发时比较喜欢这种“模块之间轻连接”的方式挑战页只负责告诉成就管理器答题结果具体成就规则由管理器处理。这样挑战页不会变得太重。十一、结果页应该展示什么限时挑战结束后结果页不能只写一个“完成”。我设计时会考虑展示这些信息总题数。正确数。错误数。总用时。是否可以重新挑战。是否可以回到练习。结果页的目的不是评价用户而是帮助用户判断下一步要做什么。如果错题多就去错题本如果正确率高就可以提高难度。十二、我开发挑战模块的总结挑战模块是整个项目里状态最多的部分。我的开发经验是 不同模式状态分开维护。 每日题要按日期同步。 练习题要筛选后打乱。⏱️ 限时挑战用阶段状态控制。 错题复习要形成学习闭环。 答题结果一定要给解析。做题不是目的帮助用户掌握知识才是目的。挑战模块正是把“资料查询型 App”升级成“学习训练型 App”的关键。
【OpenHarmony/HarmonyOs 】化学题库挑战模块实践:每日一题、练习模式与限时挑战
发布时间:2026/7/8 1:54:39
【OpenHarmony/HarmonyOs 】化学题库挑战模块实践每日一题、练习模式与限时挑战「化学视界」不是只提供资料查询也提供题库挑战功能。用户可以做每日题、普通练习、限时挑战也可以复习错题。本文记录我是如何开发挑战模块的。一、挑战模块的定位学习 App 只看资料是不够的。化学知识需要通过练习巩固所以我给项目设计了挑战模块。挑战模块包含四个入口⏱️ 限时挑战。 每日一题。✍️ 练习模式。 错题复习。这四个入口对应不同学习场景限时挑战训练速度和掌握程度。每日一题保持学习习惯。练习模式按难度和分类刷题。错题复习针对薄弱点补强。二、题目模型设计题目数据中包含题干、选项、答案、解析、分类和难度。页面展示时可以根据这些字段决定标签、颜色和筛选条件。挑战页中常用状态如下StateselectedTab: number 0;StateselectedLevel:all|middle|highall;StateselectedDifficulty:all|easy|medium|hardall;StatedailyQuestion: QuizQuestion | null null;StateselectedAnswer: string ;StateisAnswered: boolean false;StateisCorrect: boolean false;我把不同模式的状态拆开维护虽然字段看起来多但逻辑更清楚。三、每日一题按日期同步题目每日一题的关键是同一天保持同一道官方题跨天自动刷新。项目中的同步逻辑如下syncDailyForCalendarDay():void{consttoday newDate();constmo today.getMonth() 1;constda today.getDate();constdateKey ${today.getFullYear()}-${mo 10?0 mo : mo}-${da 10?0 da : da};constofficial getDailyQuestion();if(dateKey !this.lastDailyCalendarKey) {this.lastDailyCalendarKey dateKey;this.dailyQuestion official;this.currentDailyId official.id;this.viewingOfficialDailytrue;this.isAnsweredfalse;this.selectedAnswer; } }我开发这个功能时重点处理的是“同一天内不要反复重置用户状态”。如果用户已经换了一题或已经作答页面刷新时不应该突然覆盖。四、练习模式筛选题目池再打乱练习模式支持按学段和难度筛选loadPracticeQuestions() { let pool: QuizQuestion[] [];if(this.selectedLevel all) { pool quizData.slice(); }else{ pool getQuestionsByLevel(this.selectedLevel); }if(this.selectedDifficulty !all) { pool pool.filter((q: QuizQuestion) q.difficulty this.selectedDifficulty); }this.shuffleArray(pool);this.practiceQuestions pool;this.currentPracticeIndex 0; }这里的开发思路是先根据学段选题。再根据难度过滤。最后打乱顺序。每次切换条件都重置当前进度。五、洗牌算法避免每次都是同样顺序题目打乱使用常见的交换方式shuffleArray(arr: QuizQuestion[]) {for(leti arr.length-1; i 0; i--) {constj Math.floor(Math.random() * (i 1));consttemp arr[i]; arr[i] arr[j]; arr[j] temp; } }这样用户每次进入练习时题目顺序都不一样减少机械背答案的情况。六、限时挑战设置、答题、结果三阶段限时挑战页面中我把挑战状态分成三种StateprivatechallengeState: string setup;StateprivatequestionCount: number 10;StateprivatetimePerQuestion: number 60;Stateprivatequestions: QuizQuestion[] [];StateprivatecurrentIndex: number 0;StateprivateremainingSeconds: number 0;三个阶段分别是setup设置题目数量、分类、时间。playing正在答题。result展示答题结果。这样的状态机结构比用一堆布尔值更清晰。七、挑战设置用户自己控制难度限时挑战允许用户选择学段。知识分类。题目数量。每题时间。时间选项定义如下privatetimeOptions: TimeOption[] [ { value:0,name:不限}, { value:30,name:30秒}, { value:60,name:1分钟}, { value:90,name:1分半} ];我没有强制所有用户都限时因为学习阶段不同。有些用户想练速度有些用户只是想慢慢复习。八、题目标签让用户知道自己在做什么挑战页中我写了一个题号展示函数getQuestionChipText(question:QuizQuestion,mode:number):string{if(mode 1) {return第${this.currentPracticeIndex 1}题; }if(mode 2) {return错题${this.wrongIndex 1}/${this.wrongQuestions.length}; }return(this.viewingOfficialDaily?今日题目:随机练习) · #${question.id}; }这个细节能让用户明确当前模式是在做每日题、练习题还是错题复习。九、答题反馈正确和错误都要有解释挑战模块里用户提交答案后不会只显示“对/错”还会展示解析。学习类 App 的重点不是判分而是帮助用户理解。因此我设计答题流程时把“结果状态”和“解析展示”放在一起未作答展示选项和提交按钮。已作答展示正确答案、用户答案、解析。答错加入错题本。答对错题可以从错题本移除。十、挑战模块和成就系统的联动挑战模块不是孤立功能。用户答题之后成就系统也会记录行为recordQuizAnswer(correct: boolean, quizId: string): void {if(correct) {this.statistics.dailyQuizCorrect 1;this.checkAndUnlock(quiz_correct_5,this.statistics.dailyQuizCorrect);this.checkAndUnlock(quiz_correct_20,this.statistics.dailyQuizCorrect); }this.scheduleSave(); }这样用户做题不只是得到当前分数还会转化成长期成就。我开发时比较喜欢这种“模块之间轻连接”的方式挑战页只负责告诉成就管理器答题结果具体成就规则由管理器处理。这样挑战页不会变得太重。十一、结果页应该展示什么限时挑战结束后结果页不能只写一个“完成”。我设计时会考虑展示这些信息总题数。正确数。错误数。总用时。是否可以重新挑战。是否可以回到练习。结果页的目的不是评价用户而是帮助用户判断下一步要做什么。如果错题多就去错题本如果正确率高就可以提高难度。十二、我开发挑战模块的总结挑战模块是整个项目里状态最多的部分。我的开发经验是 不同模式状态分开维护。 每日题要按日期同步。 练习题要筛选后打乱。⏱️ 限时挑战用阶段状态控制。 错题复习要形成学习闭环。 答题结果一定要给解析。做题不是目的帮助用户掌握知识才是目的。挑战模块正是把“资料查询型 App”升级成“学习训练型 App”的关键。