【OpenHarmony/HarmonyOs 】限时答题状态机实践:倒计时、暂停、自动提交与实况窗结束态设计

📅 2026/7/6 1:20:15
【OpenHarmony/HarmonyOs 】限时答题状态机实践:倒计时、暂停、自动提交与实况窗结束态设计
【OpenHarmony/HarmonyOs 】限时答题状态机实践倒计时、暂停、自动提交与实况窗结束态设计项目类型OpenHarmony / HarmonyOS ArkTS 数学学习应用项目名称数学视界对应主题实况窗、全场景智慧生活、端侧 AI关键词ArkTS、倒计时、限时答题、状态机、自动提交、实况窗 ⏱️一、这篇文章写什么之前已经写过答题结果页和题型渲染这篇只聚焦“答题进行中”的状态管理倒计时、暂停、自动提交和结束态。数学视界的QuizPage.ets已经具备限时答题基础记录总用时每题限时倒计时暂停状态时间到自动提交切题时重置倒计时完成后生成结果数据。这些状态非常适合扩展到“实况窗”思路把正在进行的挑战展示成系统级持续状态。二、核心状态答题过程不是一个布尔值答题页状态包括StatecurrentIndex: number 0StateuserAnswers: string[] []StatequestionStartTime: number 0StatetotalTimeSpent: number 0StateshowAnalysis: boolean falseStateisSubmitting: boolean falseStatequestionTimer: number 0StateisPaused: boolean false这些状态共同描述答题过程当前第几题用户答案总用时当前题剩余时间是否暂停是否正在提交是否显示解析。这就是一个小型状态机。三、启动计时器总用时和题目倒计时分开startTimer()中有两个计时器startTimer(): void {if(this.timerHandler 0) { clearInterval(this.timerHandler) }this.timerHandler setInterval(() {if(!this.isPaused) {this.totalTimeSpent } },1000) }总用时只关心整个挑战持续了多久。只要没有暂停就每秒增加。题目倒计时则和配置有关if(cfg.timeLimit ! undefined cfg.timeLimit 0) {this.questionTimer cfg.timeLimitthis.questionTimerHandler setInterval(() {if(!this.isPaused this.questionTimer 0) {this.questionTimer--if(this.questionTimer 0) {this.autoSubmit() } } },1000) }这里的设计很清楚totalTimeSpent是全局questionTimer是单题isPaused同时控制两者。四、暂停状态机里的关键开关用户点击关闭按钮时会进入确认退出状态.onClick(() {this.pulseAnim(close_quiz)this.showConfirmExit truethis.isPaused true})暂停后总用时不再增加单题倒计时不再减少用户可以决定继续或退出。这比简单clearInterval()更灵活因为继续答题时不用重新创建整套状态只要恢复isPaused。五、自动提交时间到就是一次提交时间归零后调用autoSubmit(): void { this.submitCurrentQuestion() }提交逻辑submitCurrentQuestion(): void {if(this.isSubmitting)returnthis.isSubmitting truethis.showAnalysis trueif(this.questionTimerHandler 0) { clearInterval(this.questionTimerHandler)this.questionTimerHandler -1} }这里有两个细节isSubmitting防止重复提交提交后清掉单题倒计时避免解析状态还继续倒计时。六、下一题重置单题状态进入下一题时nextQuestion(): void {this.isSubmitting falsethis.showAnalysis falseif(this.currentIndex this.questions.length -1) {this.currentIndexthis.questionStartTime Date.now()this.userAnswers [...this.userAnswers]if(cfg.timeLimit ! undefined cfg.timeLimit 0) {this.questionTimer cfg.timeLimitthis.questionTimerHandler setInterval(() {if(!this.isPaused this.questionTimer 0) {this.questionTimer--if(this.questionTimer 0) {this.autoSubmit() } } },1000) } }else{this.finishChallenge() } }每题都有自己的倒计时周期。进入下一题后隐藏解析解除提交中状态切换题号重新设置倒计时。七、结束挑战停止计时并生成结果完成最后一题后finishChallenge(): void {this.stopTimer()constcorrectCount this.calculateCorrect()consttotalTime this.totalTimeSpentconstscore Math.round((correctCount /this.questions.length) *100) }然后构造结果对象const resultData:ChallengeResult{id:Date.now().toString(),config:this.config??{gradeId:,knowledgeIds:[],questionCount:0},startTime:this.questionStartTime-totalTime*1000,endTime:Date.now(),questions:challengeQuestions,correctCount,totalCount:this.questions.length,totalTime,score,gradeId:this.config?.gradeId??,knowledgeIds:this.config?.knowledgeIds??[],isCompleted:true, }这就是从“答题中状态”到“结果页状态”的转换。八、退出页面时清理计时器生命周期中调用aboutToDisappear(){ this.stopTimer() }清理函数stopTimer(): void {if(this.timerHandler 0) { clearInterval(this.timerHandler)this.timerHandler -1}if(this.questionTimerHandler 0) { clearInterval(this.questionTimerHandler)this.questionTimerHandler -1} }这能避免页面退出后计时器还在后台运行。九、实况窗设计当前项目可扩展的状态模型如果后续接入实况窗可以从现有状态直接构造interfaceQuizLiveState {currentIndex:numbertotalCount:numberremainingSeconds:numbertotalTimeSpent:numberstatus:running|paused|analysis|finished}映射关系isPaused true暂停showAnalysis true解析中questionTimer剩余秒数currentIndex 1当前题号finishChallenge()结束态。实况窗可以展示数学挑战 3/10 剩余12秒 当前状态答题中结束时可以展示挑战完成80 分 用时 3分20秒注意当前项目还没有实际接入系统实况窗这里是基于现有状态机的扩展设计。十、总结这篇文章贴合“实况窗、全场景智慧生活”主题重点不是泛讲实况窗而是从项目已有倒计时状态出发。核心实现包括⏱ 用totalTimeSpent记录总用时⌛ 用questionTimer记录单题倒计时⏸ 用isPaused控制暂停 用autoSubmit()处理时间到自动提交 提交后进入解析状态 页面退出时清理计时器 可扩展为实况窗运行态、暂停态、解析态和结束态。限时答题的核心不是倒计时本身而是状态之间的流转。状态清楚后续接入实况窗就有了基础。✨