
【OpenHarmony/HarmonyOs 】知识挑战模块拆解题库筛选、限时模式、暂停续答与成绩统计本文基于我的 OpenHarmony/HarmonyOS 项目「物理视界 PhysicsVision」整理。项目中的「物理挑战」模块包含本地题库、年级筛选、分类筛选、题目数量选择、限时模式、暂停续答、连对统计和成绩记录。这一篇单独拆解挑战模块的完整交互链路。一、挑战模块的定位物理模型负责“理解”公式计算器负责“验证”挑战模块则负责“巩固”。学习 App 如果只有内容展示很容易停留在浏览加入挑战后用户才会产生反馈我掌握了吗哪个分类容易错当前正确率如何是否需要回到模型继续学习所以挑战模块是学习闭环中的关键一环。二、题目数据结构项目先定义了题目接口interfaceQuizQuestion{ question:stringoptionA:stringoptionB:stringoptionC:stringoptionD:stringanswer: number category:stringgrade:stringexplanation:string}每道题包含题干A/B/C/D 四个选项正确答案索引所属分类年级解析。这套结构足够支撑筛选、答题、解析、统计和后续错题本。三、挑战状态管理页面使用多个State管理答题流程StatequizState: string homeStatecurrentQ: number 0Statescore: number 0StateselectedAnswer: number -1Stateanswered: boolean falseStatetotalQuestions: number 10Statestreak: number 0StatemaxStreak: number 0StatetimeLimit: number 0StatetimeLeft: number 0其中quizState控制页面状态home挑战首页playing答题中result结果页。这种状态机思路很适合复杂交互页面。四、年级与分类筛选题库支持两个筛选维度StateselectedGrade: string 全部StateselectedCategory: string 全部privategrades: string[] [全部,初中,高一,高二,高三] privatecategories: string[] [全部,力学,电磁学,光学,热学,波动]筛选函数如下getFilteredQuestions(): QuizQuestion[] {constfiltered: QuizQuestion[] []for(let i 0; i this.allQuestions.length; i) {constq this.allQuestions[i]constgradeMatch this.selectedGrade 全部|| q.grade this.selectedGradeconstcategoryMatch this.selectedCategory 全部|| q.category this.selectedCategoryif(gradeMatch categoryMatch) { filtered.push(q) } }returnfiltered }这样学生可以选择“高一 力学”或“高三 电磁学”等组合复习更有针对性。五、随机抽题打乱后取前 N 道开始挑战前项目会先筛选题目再随机打乱shuffleAndPick():void{constfiltered this.getFilteredQuestions()constshuffled:QuizQuestion[] []for(leti 0; i filtered.length; i) { shuffled.push(filtered[i]) }for(leti shuffled.length-1; i 0; i--) {constj Math.floor(Math.random() * (i 1))consttemp shuffled[i] shuffled[i] shuffled[j] shuffled[j] temp }this.currentQuestions []constcount Math.min(this.totalQuestions, shuffled.length)for(leti 0; i count; i) {this.currentQuestions.push(shuffled[i]) } }这里使用了经典洗牌算法。如果题库数量不足则取实际可用数量避免越界。六、开始挑战startQuiz(): void {this.shuffleAndPick()if(this.currentQuestions.length 0)returnthis.currentQ 0this.score 0this.selectedAnswer -1this.answered falsethis.cardAnim falsethis.hasPausedQuiz falsethis.streak 0this.maxStreak 0this.quizState playingsetTimeout(() { animateTo({ duration:600, curve: curves.springCurve(0,1,328,28) }, () {this.cardAnim true})this.startQuestionTimer() },100) }开始时会重置答题状态、得分、连对数并切换到答题页。动画结束后启动计时器。七、限时模式挑战页支持每题不限时、30 秒、15 秒ForEach([0,30,15],(sec: number){ Text(sec 0?无限制: sec.toString() s) .onClick((){ this.timeLimit sec }) })计时器逻辑startQuestionTimer(): void {this.stopQuestionTimer()if(this.timeLimit 0)returnthis.timeLeft this.timeLimitthis.questionTimerId setInterval(() {this.timeLeft--if(this.timeLeft 0) {this.stopQuestionTimer()if(!this.answered) {this.answered truethis.selectedAnswer -1this.streak 0} } },1000) }超时后自动标记为已答选项为-1连对清零。八、暂停与继续挑战模块支持暂停pauseQuiz(): void {this.stopQuestionTimer()this.hasPausedQuiz truethis.quizState home}继续答题resumeQuiz(): void {this.hasPausedQuiz falsethis.cardAnim falsethis.quizState playingif(this.answered) {// 保持已答状态让用户点下一题}else{this.selectedAnswer -1} }这个设计很贴近真实使用场景。学生可能中途切出去看公式、查模型或处理别的事回来后可以继续挑战。九、选择答案与连对统计selectOption(index: number): void {if(this.answered)returnthis.stopQuestionTimer()this.selectedAnswer indexthis.answered trueconstq this.currentQuestions[this.currentQ]if(index q.answer) {this.scorethis.streakif(this.streak this.maxStreak)this.maxStreak this.streak }else{this.streak 0} }逻辑很直接已答过就不能重复选择选中后停止计时答对加分和连对答错连对清零。这类即时反馈能增强挑战感。十、完成挑战与最高分记录最后一道题完成后this.totalPlayedconstpct this.currentQuestions.length 0? Math.round(this.score /this.currentQuestions.length *100) :0if(pct this.highScore) {this.highScore pct }this.quizState result这里使用StorageLink保存挑战次数和最高正确率StorageLink(highScore)highScore: number 0StorageLink(totalPlayed)totalPlayed: number 0这些数据还会被设置页、成就页读取形成全局学习状态。总结挑战模块看起来只是答题但实际上包含一条完整链路筛选题库 → 随机抽题 → 开始挑战 → 限时答题 → 暂停续答 → 判断正误 → 统计成绩 → 更新学习状态。对 OpenHarmony/HarmonyOS 应用开发来说这类模块很适合用状态驱动实现。只要把答题流程拆清楚ArkUI 的响应式状态就能让页面自然跟随数据变化。