【OpenHarmony/HarmonyOs 】限时答题状态机实践:倒计时、暂停、自动提交与实况窗结束态设计
📅 2026/7/6 1:39:45
👁️ 阅读次数
📝 编程学习
【OpenHarmony/HarmonyOs 】限时答题状态机实践:倒计时、暂停、自动提交与实况窗结束态设计
项目类型:OpenHarmony / HarmonyOS ArkTS 数学学习应用
项目名称:数学视界
对应主题:实况窗、全场景智慧生活、端侧 AI
关键词:ArkTS、倒计时、限时答题、状态机、自动提交、实况窗 ⏱️
一、这篇文章写什么?
之前已经写过答题结果页和题型渲染,这篇只聚焦“答题进行中”的状态管理:倒计时、暂停、自动提交和结束态。
数学视界的QuizPage.ets已经具备限时答题基础:
- 记录总用时;
- 每题限时倒计时;
- 暂停状态;
- 时间到自动提交;
- 切题时重置倒计时;
- 完成后生成结果数据。
这些状态非常适合扩展到“实况窗”思路:把正在进行的挑战展示成系统级持续状态。
二、核心状态:答题过程不是一个布尔值
答题页状态包括:
@StatecurrentIndex: number =0@StateuserAnswers: string[] = []@StatequestionStartTime: number =0@StatetotalTimeSpent: number =0@StateshowAnalysis: boolean = false@StateisSubmitting: boolean = false@StatequestionTimer: number =0@StateisPaused: 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.currentIndex++this.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()处理时间到自动提交; - 📖 提交后进入解析状态;
- 🧹 页面退出时清理计时器;
- 🚀 可扩展为实况窗运行态、暂停态、解析态和结束态。
限时答题的核心不是倒计时本身,而是状态之间的流转。状态清楚,后续接入实况窗就有了基础。✨
编程学习
技术分享
实战经验