全局计时器、智能提醒与UI交互实现

发布时间:2026/6/12 23:16:03

全局计时器、智能提醒与UI交互实现 本文分享「灶台导航」小程序中多菜谱烹饪的运行机制包括全局计时器设计、智能提醒触发逻辑以及页面交互的完整实现。一、全局计时器实现1.1 计时器完整代码这个计时器类支持开始、暂停、继续、停止并且支持注册多个回调函数/** * 多菜谱全局计时器 * 核心功能统一时间基准、支持暂停/继续、每秒通知所有监听者 */ class GlobalCookTimer { constructor() { this.startTime null // 开始时间戳毫秒 this.elapsedTime 0 // 已经过的秒数 this.intervalId null // 定时器ID this.isRunning false // 是否运行中 this.isPaused false // 是否暂停中 this.pauseTime 0 // 暂停时的时间戳 this.callbacks [] // 回调函数列表 } /** * 开始计时 */ start() { this.startTime Date.now() this.isRunning true this.isPaused false this.intervalId setInterval(() { this.tick() }, 1000) } /** * 暂停 */ pause() { if (!this.isRunning || this.isPaused) return this.isPaused true this.pauseTime Date.now() clearInterval(this.intervalId) }/** * 继续核心补偿暂停时间 * 原理startTime 向后移动 pauseDuration仿佛暂停从未发生 */ resume() { if (!this.isPaused) return // 计算暂停了多久 const pauseDuration Date.now() - this.pauseTime // 调整开始时间补偿暂停时长 this.startTime pauseDuration this.isPaused false this.intervalId setInterval(() { this.tick() }, 1000) } /** * 停止 */ stop() { clearInterval(this.intervalId) this.isRunning false this.isPaused false }/** * 每秒执行一次更新经过时间并通知回调 */ tick() { this.elapsedTime Math.floor((Date.now() - this.startTime) / 1000) this.callbacks.forEach(cb cb(this.elapsedTime)) } /** * 注册回调 */ onTick(callback) { this.callbacks.push(callback) }/** * 获取当前时间支持暂停时正确返回 */ getElapsed() { if (this.isPaused) { return Math.floor((this.pauseTime - this.startTime) / 1000) } return Math.floor((Date.now() - this.startTime) / 1000) } /** * 销毁 */ destroy() { this.stop() this.callbacks [] } }1.2 暂停补偿原理图解用户暂停10分钟的场景 暂停前 startTime 12:00:00 当前经过时间 300秒 当前真实时间 12:05:00 用户点击暂停10分钟后点击继续 暂停时长 600秒 新startTime 12:00:00 600 12:10:00 恢复后计算经过时间 当前真实时间 12:15:00 经过时间 12:15:00 - 12:10:00 300秒 ✅ 效果仿佛那10分钟从未存在过计时器继续从300秒开始1.3 页面集成代码// pages/cook/cook.js Page({ data: { schedule: null, elapsedSeconds: 0, currentTasks: [], completedSteps: [] }, globalTimer: null, onLoad(options) { const recipeIds JSON.parse(options.recipes || []) this.loadAndCalculate(recipeIds) }, onUnload() { // 页面销毁时清理计时器防止内存泄漏 if (this.globalTimer) { this.globalTimer.destroy() } }, async loadAndCalculate(recipeIds) { const recipes await this.loadRecipes(recipeIds) const schedule calculateSchedule(recipes) this.setData({ schedule }) this.initTimer(schedule) }, initTimer(schedule) { this.globalTimer new GlobalCookTimer() this.globalTimer.onTick((elapsed) { this.onTimerTick(elapsed) }) this.globalTimer.start() }, onTimerTick(elapsed) { const { schedule } this.data this.setData({ elapsedSeconds: elapsed }) // 获取当前应该执行的任务 const currentTasks this.getCurrentTasks(elapsed) if (currentTasks.length 0) { this.setData({ currentTasks }) this.checkNewTasks(currentTasks) } this.checkCompletedTasks(elapsed) // 检查是否全部完成 if (elapsed schedule.totalDuration) { this.onAllComplete() } }, /** * 获取当前时间点正在进行的任务 * 核心逻辑判断 elapsed 是否在步骤的 [start, end) 区间内 */ getCurrentTasks(elapsed) { const tasks [] this.data.schedule.recipes.forEach(recipe { recipe.steps.forEach(step { if (elapsed step.globalStartTime elapsed step.globalEndTime) { tasks.push({ recipeId: recipe.recipeId, recipeName: recipe.recipeName, step, remaining: step.globalEndTime - elapsed // 剩余秒数 }) } }) }) return tasks } })二、提醒机制实现2.1 提醒管理器完整代码/** * 提醒管理器 * 功能检测关键节点触发语音提醒防止重复提醒 */ class ReminderManager { constructor(ttsQueue) { this.ttsQueue ttsQueue // 语音队列处理异步播放 this.reminded new Set() // 已提醒过的任务ID用于去重 } /** * 检查是否需要提醒每秒调用一次 */ check(elapsed, schedule) { // 检查即将开始的任务提前30秒提醒 schedule.timeline.forEach(event { if (event.type start) { const timeToStart event.time - elapsed if (timeToStart 0 timeToStart 30 !this.reminded.has(start-${event.time})) { this.reminded.add(start-${event.time}) this.remindTaskStart(event) } } }) // 检查即将结束的任务提前10秒提醒 schedule.timeline.forEach(event { if (event.type end) { const timeToEnd event.time - elapsed if (timeToEnd 0 timeToEnd 10 !this.reminded.has(end-${event.time})) { this.reminded.add(end-${event.time}) this.remindTaskEnd(event) } } }) } remindTaskStart(event) { const text ${event.recipeName}即将开始第${event.step.order}步 this.ttsQueue.add(text) } remindTaskEnd(event) { const text ${event.recipeName}第${event.step.order}步即将完成 this.ttsQueue.add(text) } reset() { this.reminded.clear() } }2.2 提前量设计说明提醒类型提前量设计原因任务开始30秒给用户30秒准备时间比如洗手、拿食材任务结束10秒防止烧干锅10秒足够用户走到灶台前剩余时间10分钟/5分钟/1分钟整点提醒让用户把握整体进度2.3 周期性时间提醒/** * 周期性时间提醒 * 在关键剩余时间点提醒用户 */ function setupPeriodicReminder(timer, schedule) { // 关键时间节点秒10分钟、5分钟、1分钟、30秒、10秒 const reminderPoints [600, 300, 60, 30, 10] const reminded new Set() timer.onTick(elapsed { const remaining schedule.totalDuration - elapsed reminderPoints.forEach(point { // 当剩余时间首次小于等于某个节点时触发提醒 if (remaining point remaining point - 5 !reminded.has(point)) { reminded.add(point) announceRemaining(remaining) } }) }) } function announceRemaining(seconds) { let text if (seconds 600) { text 还有${Math.floor(seconds / 60)}分钟 } else if (seconds 60) { text 还有${Math.floor(seconds / 60)}分钟 } else { text 还有${seconds}秒 } ttsQueue.add(text) }三、UI 展示3.1 页面模板代码!-- 多菜谱烹饪页面 -- view classmulti-cook-container !-- 时间概览 -- view classtime-overview text classelapsed{{elapsedDisplay}}/text text classtotal/ {{totalDurationDisplay}}/text /view !-- 进度条 -- view classprogress-bar view classprogress-fill stylewidth: {{progress}}%/view /view !-- 当前任务列表 -- view classcurrent-tasks view classtask-card wx:for{{currentTasks}} wx:keyrecipeId view classtask-header text classrecipe-name{{item.recipeName}}/text text classstep-label步骤 {{item.step.order}}/text /view view classtask-content{{item.step.content}}/view view classtask-footer text classremaining剩余 {{item.remaining}}秒/text /view /view /view !-- 控制按钮 -- view classcontrols button wx:if{{!isPaused}} bindtaponPause暂停/button button wx:if{{isPaused}} bindtaponResume继续/button /view /view3.2 UI 交互说明UI 元素数据绑定更新频率作用时间概览elapsedDisplay每秒让用户知道当前进度进度条progress%每秒视觉化整体进度任务卡片currentTasks任务变化时显示当前该做什么剩余时间remaining每秒紧迫感提示控制按钮isPaused点击时暂停/继续计时3.3 任务卡片显示逻辑可以显示多个卡片比如红烧肉在炖wait类型同时番茄蛋汤在准备cook类型两个任务可以并行剩余时间倒计时每秒递减让用户感知紧迫程度完成任务自动移除当 elapsed globalEndTime 时该任务卡片消失四、总结模块核心职责关键代码设计要点全局计时器统一时间基准支持暂停GlobalCookTimer 类暂停补偿算法任务检测实时判断当前该做什么getCurrentTasks()区间比较 状态机提醒机制关键节点语音播报ReminderManager 类提前量 去重队列UI交互信息展示与用户控制WXML 数据绑定多任务卡片 进度条整套系统让用户可以无脑跟着指引走系统自动告诉你接下来该做什么、什么时候做、还剩多久大大降低了多菜同时烹饪的心智负担。

相关新闻