Commit Graph

36 Commits

Author SHA1 Message Date
lc f1ad3eeb95 feat(timer): 训练时长低于阈值不记录并明确提示
- config.js 新增 minRecordSeconds: 20 阈值配置,改配置即可调整门槛
- timer.js: finishTraining/_onCircuitComplete 低时长不播完成语音;
  _saveAndShowCompletion 兜底判断,任何入口都不会把短时训练落库;
  新增 _showNotRecorded: 不保存记录、不更新连胜,复用完成弹窗展示实际秒数
- timer.wxml/wxss: 完成弹窗新增"未计入记录"提示行(门槛说明),
  未记录时隐藏"查看记录/分享"按钮,只留"再来一次+回到首页"
- 修复状态残留: 未记录后点"再来一次",下次正常完成不会误显示"未计入记录"
2026-08-12 10:20:40 +08:00
lc 05c4763e49 feat(timer): 循环训练组进度改为圆环分段弧 + 信息气泡三行合一
- progress-ring 新增 sets/currentSet/resting/successColor 属性,
  圆环外圈绘制分段弧(已完成=主色/当前=呼吸光点/休息下一组=绿),单组模式零渲染
- timer 删除顶部 circuit-bar 进度面板,布局骨架三模式统一
- 呼吸环淡化(描边 0.55→0.20,柔光渐变强度减半)
- 目标卡与提示气泡合并为 info-bubble,状态文案(撑住/休息中/已暂停)并入气泡顶部
2026-08-12 09:39:41 +08:00
lc 0464eeaba6 feat(timer): 训练页改版 hero 风格 + 进度环刻度 + 醒目姿态提示气泡
- progress-ring: canvas 新增秒刻度层(四分位加粗), 环内加 subText, 移除组件内 statusText
- timer.wxml: 环下方状态词 + 目标信息卡(今日目标·第N天›静态箭头) + 运行提示; 进度环传 ticks/subText
- timer.js: 派生 ringTicks/ringSubText/statusText/goalLine/runningTip/tipType/tipIcon, 各生命周期计算下发
- timer.wxss: 按钮贴底(flex-start+margin-top:auto), 新增 .timer-status/.goal-card/.timer-tip 气泡卡片(主色左边框+小三角+tipPulse 呼吸), 文字放大加粗
- 姿态提示分语义: posture/phase(主色) / done(成功色), 图标用 peopleFill/successFill
- 状态机/计时/循环FSM/呼吸环/彩带/弹窗/语音震动常亮全部保留
- 另含 index 进度地图右上角奖杯图标删除(quest-trophy 样式清理)
2026-08-11 15:38:37 +08:00
lc 187c426243 chore: 上线前优化 — 清理调试日志/启用组件按需注入/补全组件声明
- 移除全项目 34 处调试 console.* 输出
- project.config.json: minified true、uploadWithSourceMap false、启用 lazyCodeLoading(requiredComponents 组件按需注入)
- pages/records/records.json 补全 ui-skeleton 组件声明(此前漏声明,WXML 已使用)
- 删除根目录残留 preview-buttons.html
2026-08-04 14:05:16 +08:00
lc b52db87ddf feat: 排行榜虚拟领奖台 + 勋章对齐与尺寸统一
- 领奖台数据不足 3 名时显示虚拟空位(虚线轮廓+虚位以待)
- 领奖台勋章与昵称对齐改为等高盒结构性修复(移除 margin 盲推)
- 全 app 成就勋章图标尺寸统一为 30rpx(前三名/列表/设置页/记录页一致)
- 勋章 SVG 按包围盒精确居中(utils/icons.js)
- 设置页/记录页勋章展示配套调整
2026-08-04 11:23:48 +08:00
lc 3532d0111b feat: 循环训练模式 + 语音补全 / 屏幕常亮 / 卡片渲染修复
循环训练(circuit)
- 新增 utils/circuitTimer.js 状态机: 工作->休息->...->完成, stop() 返回有效撑总秒(不含休息)
- 首页新增「循环训练·分组练习」入口 + stepper 配置弹窗
- 配置本地持久化 circuit_config(每组时长/组数/休息/每周目标), 下次自动预填
- 记录以 planId:'circuit' + mode:'circuit' 落库, duration 语义不变 -> 排行榜/统计/每日计划进度零改动
- 记录页展示「循环 N组xMs·休Rs」

计时器顶部循环进度面板
- 组进度点阵按组数等分铺满(flex:1 1 0, 去掉 max-width 封顶), 当前组以增高而非加宽强调
- 大号「X/Y 组」+ 四态阶段徽章(撑住/休息中/准备开始/已暂停) + 累计秒数副行
- 状态灯用纯 CSS 圆点(SVG 图标颜色烤死在 data URI 里, CSS 改不动)
- 超过 15 组自动降级为线性进度条; 面板不设固定高度, 规避真机大字体档裁字

修复: 循环训练全程无语音
- 根因: circuit 的 onTick 走 _circuitCue(只有震动), 从未调用 _remind
- 接入整场进度播报, 基准为 sets x holdPerSet(而非每组), 避免 4 组播 4 次「已完成一半」
- 新增 restStart/nextSet/lastSet 三条不含数字的词条, 客户端与 tts 云函数词表同步
- 修复必然撞车的时序: 偶数组时 halfway 与休息切换同一 tick, 加 2.6s 优先窗口让位
- 防吵闸门: 每组 <10s 不播过场语音, 休息 <5s 不播; 预载按模式取词条

训练期间屏幕常亮
- wx.setKeepScreenOn: onStart 开 / onUnload 关 / onShow 在 isRunning 时重新武装
- 切后台再回来该标志会被系统清掉, 故必须重新武装, 否则后半程丢语音与震动
- 低基础库与 Android 省电模式静默降级, 不弹 toast

修复: 首页打卡卡片左侧两个竖条
- 根因: ui-card 宿主节点无 display 声明为 inline, 页面侧加的 border 被打断成两个零宽行盒碎片
- ui-card 加 :host{display:block}, margin-bottom 从内部 view 上提到宿主
- 高亮由 border 改为 box-shadow spread 描边(不占布局, 无跳动) + 补 border-radius
- 连带修复失效的交错入场: nth-child 跨组件边界恒匹配 1, 改为 index 属性驱动内联 animation-delay, 14 处调用点补序号

注意: tts 云函数需重新部署, 否则新增的 3 条词条返回 Unknown prompt key(静默降级不报错)
2026-08-03 16:34:22 +08:00
lc 76cd2b6c0f fix: 三个 P2 小修(榜单离线兜底/同天连胜文案/热力图日期解析)
- leaderboard.js _applyLocal 离线兜底补 subText(N次),与云端路径对齐
- timer.js _detectCelebrationLevel 增加 lastIsToday 判断,修复同天二次训练连胜文案虚高 1 天
- calendar-heatmap.js 用 util.dateOnly 归一化后再取'日',修复脆弱的 split 解析
2026-07-31 10:23:44 +08:00
lc b42d080826 feat(leaderboard): 训练完强刷 + 下拉刷新 force
- 云函数 _fetchLatestByOpenid 支持 force 跳过实例缓存重新扫描
- 训练完成设 _lb_force_refresh 标志,下次打开排行榜强刷,新数据立即可见
- 下拉刷新带 force=true,拉取最新数据
- 平时常规打开仍走 5min 缓存 + 客户端乐观缓存,不增加无谓扫描

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-28 08:47:41 +08:00
liucheng 983ae1b9cb fix: 缓存击穿/play竞态/onUnload泄漏/清除数据UI/统计NaN
- leaderboard 云函数: _fetchLatestByOpenid 加 in-flight promise,并发请求复用同一次扫描,防缓存击穿
- voice: play 加序列号,丢弃过期播放,避免旧语音截断新语音
- timer: onUnload 补取消 _completionCountUp,系统返回手势不再泄漏动画定时器
- settings: 清除数据 setData 补 voiceGender/vibrateIntensity 重置,避免 UI 与存储不一致
- storage: getTotalStats 对 r.duration 防御(Number||0),避免脏数据产生 NaN 传染

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 15:01:51 +08:00
liucheng 1c140bd503 fix: 修复 4 个正确性问题(分享秒数/主题同步/云推送定位/streak重算)
- timer: 完成弹窗存实际时长 completionActualElapsed,分享改用它,避免用动画值导致秒数错误
- theme: setTheme 补 _markLocalChanged,避免云恢复覆盖未同步的主题改动
- cloud: _doPush 重定位查询补 orderBy(updatedAt desc),与 pullAll 一致,避免命中最旧文档
- storage: deleteRecord 改用 recomputeStreak,修复删连续链中间某天 streak 虚高

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 14:51:09 +08:00
liucheng b47a48259e fix: 修复审查发现的 4 个高优先级问题
- plan: getTodayTarget 补 customPlans 参数,timer/index 调用点传值,修复自定义计划每日目标失效
- leaderboard: fetchRank 加请求序列号丢弃过期响应,修复快速切换周期竞态
- leaderboard 云函数:遍历记录加防御(r.date/duration/数组校验),避免单条脏数据崩溃全榜
- tts: _upload cloudPath 补 volume/speed,避免不同音量语速音频互相覆盖

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 14:48:09 +08:00
liucheng 16924d31db perf(voice): 语音本地文件缓存 + 预加载,消除播放延迟
- 新增本地文件缓存层:downloadFile + saveFileSync 存持久本地文件,跨重启命中即出声
- _resolveSrc 三层优先:本地文件 -> 云函数 audioUrl -> 下载存本地
- 新增 preload(),timer 页 onLoad 后台预载全部语音
- 文件被清理自动回退重下载,下载失败回退临时 url

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 14:21:04 +08:00
liucheng ed7029faf9 feat(timer): 训练超时与完成展示优化 (v3.0)
- 超时后圆环底环变绿,中心改显总训练时长(MM:SS 实时涨),移除 +Xs 小徽章
- 完成弹窗成绩由纯秒数改为分秒(如 1分23秒),>=60s 时缩字号防撑破卡片
- 修复结束确认弹窗停留期间计时器未暂停导致训练时长虚增:onStop 暂停、取消恢复、确认取暂停值
- progress-ring 新增 elapsed prop,remaining=0 时中心切显总时长
- 清理废弃的 overtime 字段与 .overtime-badge 样式
- 版本号 v2.9 -> v3.0,更新日期

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 11:36:32 +08:00
liucheng e712741425 feat(share): 启用全站系统分享 + 完善分享文案配置
- 各 Page 补齐 onShareAppMessage/onShareTimeline,修复右上角转发/朋友圈按钮灰色
- ui-btn 透传 open-type,完成弹窗接入分享按钮
- config.share 集中维护文案,动态标题用 titleTemplate 占位符
- leaderboard 的 myEntry.rank 缺失时回退静态标题,避免出现"排第 undefined"
- 完成弹窗分享按钮高度对齐 88rpx,与同排按钮等高

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-25 11:03:02 +08:00
lc 6176f2c341 feat(ui): 记录页月份联动与多项 UI 美化/修复
- records: 底部列表与月份选择器联动,新增 [本月|最近] 分段控件;标题/空态随模式切换
- leaderboard: 领奖台布局(冠军居中+皇冠)、次数标注于底座且三档水平对齐;头像 cloud:// 批量预解析提速(云函数需重新部署)
- index/timer: 主色底图标改白色变体修复隐形;目标数字按微信字体缩放补偿真机遮挡
- settings: 配色方案横滑渐变色卡;头像上传前压缩至 200px
- theme: 新增 teal 主题;暗黑背景统一对齐
- 圆形头像双保险(image 自身 border-radius)修复月/年榜方图

注: cloudfunctions/leaderboard 改动须在开发者工具重新部署才生效。
2026-07-22 09:36:22 +08:00
lc 1eff3d60c4 fix(ui): 多项 UI 修复 — 弹窗遮挡/按钮可见性/暗黑闪烁/云函数版本
- 计划编辑弹窗移出 .container 避免 fixed 降级 + 修复滚动
- dock bottom 40rpx→8rpx 紧贴底部, sheet padding 同步调整
- 计划编辑器取消/恢复默认按钮可见性修复(bg 匹配容器)
- ui-btn--danger 按钮可见性修复
- 清除确认弹窗跟随暗黑模式切换
- icons.js build() 中 Fill 路径覆盖 outlined 路径修复
- plan.js getPlanDay 忽略 customPlans 修复
- darkMode.js 冗余三元简化
- util.js fileToDataURI fallback 可读性提升
- theme.js: BASE_VARS 与 getThemeStyle 统一来源, 去 50ms navbar 延迟
- app.wxss: 移除 page transition 和 background-color 减少闪白
- 云函数 wx-server-sdk 版本统一 ~2.6.3, tts cloud.init 一致化
- 闪白问题: wx.setBackgroundColor 三层防护(onLaunch/applyThemeToPage/switchTab)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 09:40:04 +08:00
lc 885db8c18b feat(timer): 训练中轮换姿势要领 + hint 字号调大
- 训练中 hint 每 12 秒轮换一条平板支撑姿势要领(收紧核心/肩膀放松/
  别塌腰/别憋气等 10 条),替代固定文案,帮助持续纠正姿势
- 姿势文案与间隔移入 config.js(postureTips/tipInterval),统一管理
- hint 字号 28rpx -> 34rpx,图标 32rpx -> 36rpx,更易看清

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 11:04:37 +08:00
lc ed16ac5efd fix(vibrate): 修复旧用户震动失效 + 新增震动强度选项
根因:user_settings 早期无 vibrate 字段,getSettings 未兜底,
_remind 的 !s.vibrate 误判 undefined 为关闭,导致震动静默失效,
需手动操作开关才恢复。

- storage: getSettings 兜底 vibrate/voiceGuide/vibrateIntensity 默认值
- timer: !s.vibrate 改 === false,字段缺失视为开(与 voiceGuide 一致)
- timer: vibrate 按 vibrateIntensity 选 API(light/medium=vibrateShort,
  heavy=vibrateLong),fail 回调辅助排查
- settings: 新增"震动强度"三档(短促/标准/强烈),默认强烈

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 10:36:14 +08:00
lc dd9cd1859c feat(timer): 训练到目标时长不再自动结束,支持超长发挥
- Timer: 到时间触发 onGoalReached(提示)而非自动结束,elapsed/overtime
  继续累加直到用户手动停止
- timer: onGoalReached 播 goal 语音 + goalReached 状态;finishTraining
  补 complete 语音;完成弹窗显示"超长发挥 +X 秒"
- wxml: 超时 badge 训练中也显示;新增 goalReached hint 分支
- voice/tts: 新增 goal 语音 prompt(需部署 tts 云函数)
- config: 版本号 v2.5 -> v2.6

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 09:37:32 +08:00
lc 6fffc5aece fix: 振动定时器清理、完成保存守卫、暗黑冷启动、头像云存储
- timer: 振动 setTimeout 入栈追踪,暂停/停止/卸载/重练统一清理,
  避免页面销毁后残留震动(_clearVibrateTimers)
- timer: _saving 守卫统一到 _saveAndShowCompletion,自然完成与手动
  结束两路径都防重复保存;修复 onTrainAgain 不重置会话状态导致
  再练一次后第二次无语音/振动且保存被挡
- app.wxss: @media dark 补全 --text/--card-bg/--bg-soft/--border/
  --success/--danger,冷启动即为完整深色,不再背景深卡片白的割裂闪烁
- settings: 头像优先上传云存储存 fileID,三级回退(fileID->base64->
  临时URL),pushAll 不再每次传输图片字节

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 09:17:27 +08:00
lc 326bc013fe fix(timer): 完成页圆环覆盖弹窗 + 自定义确认 modal 替代 wx.showModal
训练完成的三个相关 bug:
1. progress-ring 圆环覆盖完成页弹窗 → @tap ring wx:if 让完成态时直接 unmount
2. 完成弹窗内按钮需要点 2 次才能响应 → completion-mask 加 catchtouchmove 拦截 touchmove
3. wx.showModal "结束训练" 系统弹窗在 stacking context 下 hit-test 不稳

根因: .timer-page.page-enter 永久保留 transform: translateY(0),
创建永久 stacking context,影响 native modal 的 WebView 部分 hit-test。

修法:
- 新增自定义 stop-confirm modal (catchtouchmove + 内部 catchtap + bindtap),
  与 ui-modal/settings.plan-editor-mask 同模式,行为可靠
- completion-mask 用相同模式拦截 touchmove
- 顺便修 overtime-badge 暗色 (rgba(var(--success-rgb)))
2026-07-08 15:21:46 +08:00
lc 503f01f6e9 feat: 训练完成全屏弹窗 (大数字+countUp+超时+3按钮)
替换原来不显眼的 wx.showToast:
- 全屏遮罩 + 大圆角卡片,scale-in 弹性入场
- 大数字 180rpx countUp 从 0 滚到实际秒数(1.2s)
- 超时标签 +Xs 秒超时(OvertimePop 弹性出现,延迟 1.1s 等数字到末尾)
- 连续打卡显示 🔥
- 3 按钮:再来一次(留在当前页重置) / 查看记录(跳记录页) / 回到首页
- 装饰 emoji 圆形 1.6s 循环脉冲
- onComplete 触发时自动保存,不需要再手动点结束
2026-07-08 14:19:40 +08:00
lc f052327276 feat: 训练完成后首页 streak 卡片高亮 3 秒
timer 记录保存时写 _last_train_at 时间戳,index onShow 检测
< 10s 的标记则触发 just-completed class,卡片脉冲 2 次 + 主题色
边框 + 阴影,3 秒后自动淡出。让'完成训练'的反馈在首页也可见。
2026-07-08 14:13:50 +08:00
lc 96d92cfe10 feat: 完成训练分级庆祝 (normal/first/milestone/record)
- normal: 12 条彩带
- record (破个人纪录): 24 条 + 横幅"🏆 新纪录!X秒"
- milestone (连击 7/14/30/50/100/365 天): 32 条 + 横幅
- first (首次训练): 40 条 + 横幅"🎉 第一次训练"

横幅 3.5s 后自动淡出,彩带时长随等级递增(2.4s → 4s)。
2026-07-08 14:13:11 +08:00
lc d192769dbe feat: timer 完成全屏彩带动画 (10 条彩色碎片飘落) 2026-07-08 11:37:25 +08:00
lc 5d810fd058 feat: timer 页面接入 countUp 数字滚动 (load 时 0→duration) 2026-07-08 11:37:13 +08:00
lc 0bba403b00 feat: 页面级入场动画 (fade + translateY) 应用到 5 个页面 2026-07-08 11:33:29 +08:00
lc 6af09e4324 fix: 防连点产生重复训练记录 + 补充遗漏的状态重置
- finishTraining 添加 _saving 防重入,避免1.5秒延迟期间连点
- _init 补充 _last30Signaled/_last10Signaled 重置,修复
  多次训练时语音提示丢失的bug

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-24 13:20:03 +08:00
lc d817d5d012 fix: 13项数据存储与排行榜修复
致命修复:
- leaderboard: 日榜日期比较改用 dateOnly() 替代严格全等
- plan: 计划天数计算日期比较改用 dateOnly()
- cloud: pullAll 添加 orderBy('updatedAt','desc') 确保取最新文档避免数据丢失

严重修复:
- cloud: 新增 cancelPendingPush() 防止清除数据后被延迟推送复活
- settings: _doClearData 补充 user_profile 清除, 先取消推送再清除
- app: 云端同步改为时间戳比对策略, 支持跨设备拉取
- app: _restoreFromCloud 增加空数据保护和 profile 恢复
- storage: 记录ID改用时间戳+自增计数器确保唯一性

中等修复:
- cloud: init/_fetchOpenid 日志升级, 新增 syncStatus getter
- leaderboard云函数: 添加90天活跃过滤减少全表扫描
- storage: validateStreak 增加lastDate无记录时的通用修复
- leaderboard页面: 云函数失败时Toast提示用户而非静默降级

轻微修复:
- timer: onUnload 添加 voice.destroy() 释放音频上下文
- records: onLongPressDelete 委托给 onDeleteRecord 消除重复代码

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-24 12:22:54 +08:00
lc 47f718a129 feat: 训练开始时添加语音播报 2026-06-11 11:51:14 +08:00
lc 1d55df72b3 feat: v1.5 — plan editor, voice prompts, UI polish
Major features:
- Training plan editor: edit preset days/duration per plan (in-place
  override via custom_plans storage; preset ids preserved so existing
  records stay valid)
- Voice prompts at 4 fixed points during training (halfway / 30s /
  10s / done) via Tencent Cloud TTS (cloudfunctions/tts + utils/voice.js)
- Free-training button: switched from outline (transparent) to ghost
  variant (theme-tinted) for visual weight

Bug fixes:
- 4 functional pages: SVG data URIs failed to render in WeChat because
  '\#' in colors was parsed as a data-URI fragment delimiter. encode the
  whole SVG via encodeURIComponent in utils/icons.js build().
- Old records (saved before id field was added) could not be deleted
  (data-id was empty, triggered defensive guard). Backfill stable
  legacy-<month>-<index>-<duration> ids in getRecords() and persist.
- settings.js plan-row editor button event was bubbling up to the row's
  bindtap (which also fired onSelectPlan). Wrapped in catch:tap.

UI:
- Settings page: 3 hardcoded plans replaced with dynamic buildPlansList
  that overlays custom_plans on top of presets
- Plan editor: bottom-sheet modal in settings page (regular view, not
  ui-modal — WeChat custom component root element drops position:fixed
  in this runtime)
- Free-training button: rounded pill style, full-width, 24rpx gap from
  primary action; bottom sheet uses max-height: 88vh + internal scroll
- Version bumped to v1.5, last updated 2026-06-10

Removed:
- Daily reminder section (dailyReminder / reminderTime) — replaced by
  the 4 voice prompts which cover the same user need without requiring
  long-term scheduling that WeChat mini-programs can't actually do

Misc:
- utils/plan.js refactored to formula-driven: presets declare
  totalDays/startTarget/increment/cycleDays, days[] is generated. Same
  formula applies to custom plans.
- Timer _remind() guards each prompt on minimum duration so short
  free-mode sessions don't fire 'last30' at the start
- Cloud storage cloud_plans field added to data push payload; restored
  on first install via _restoreFromCloud
- .gitignore added for local AI tool caches (.reasonix/, reasonix.toml,
  .codegraph/daemon.pid)
2026-06-10 17:23:13 +08:00
lc fb3bc6c045 fix: CSS custom properties not resolving from inline style
Root cause: WXSS compiler resolves var(--primary) at compile time
against page{} declarations in app.wxss. The orange defaults
(--primary:#FF6B35 etc.) were being baked into compiled WXSS,
so the inline style theme override on .container was ignored.
Records and settings pages always rendered orange regardless of
the user's theme choice.

Fix:
1. Remove --primary, --primary-light, --primary-bg, --primary-rgb
   from page{} in app.wxss, forcing WXSS to resolve var() at
   runtime from inline style on .container
2. Expand BASE_VARS in theme.js to include default orange theme
   vars, so the initial render (before onLoad) still has valid
   CSS custom properties — no flash of unstyled content
3. Export BASE_VARS from theme.js
4. Change all 4 pages + custom-tab-bar initial data.themeStyle
   from '' to themeMod.BASE_VARS, eliminating the empty-string
   gap between first render and onLoad
2026-06-04 17:03:09 +08:00
lc 8079242daf fix: theme not applying to training/records pages
Root cause: themeStyle was on .container only, but modals (picker,
day-detail) were siblings of .container in the WXML tree. CSS custom
properties set via inline style on .container don't cascade to
sibling elements — those elements fall back to app.wxss page-level
defaults (always orange). Users saw modal buttons in orange and
concluded the whole page didn't follow theme.

Fixes:
- index.wxml: Move picker modal inside .container so it inherits
  themeStyle CSS variables (position:fixed is viewport-relative,
  so nesting doesn't affect modal positioning)
- index.js, records.js: Add applyThemeToPage in onLoad alongside
  onShow, preventing a flash of default orange before onShow fires
- timer.js: Add onShow with applyThemeToPage as lifecycle safety
  net; extract _init from onLoad for clean separation
2026-06-04 16:53:53 +08:00
lc 89d93c8155 refactor(ui): 12-point UI polish and bugfixes
Bug fixes:
- #1 Remove duplicate month label from calendar-heatmap (shown twice in records)
- #2 Extract shared .modal-overlay to app.wxss (was duplicated in index/records)

UX improvements:
- #3 Add long-press hint to history list in records page
- #4 Add drag handle + catchtouchmove to picker modal
- #5 Extend timer auto-navigate-back from 1.5s to 3s
- #6 Add clear data option in settings with confirmation dialog

Visual/code polish:
- #7 Remove 4 unused @keyframes (shimmer, spin) and 5 unused .icon classes
- #8 Tab bar inactive colors: hardcoded #888/#666 -> var(--text-secondary)
- #10 Split progress-ring observer to avoid redundant setData on size/color changes
- #12 Remove meaningless Math.min(planDay, 99) cap
2026-06-04 16:34:22 +08:00
lc 8c7f633541 refactor: ES6+ modernization + 2 bugfixes
- var→const/let, function→arrow/class across all 13 JS files
- Timer: prototype→class with ES6 getters
- plan days: IIFE→Array.from declarative generation
- storage/plan: unified formatDate via util.js
- Bugfix: getPlanDay now filters by planId (plan switch accuracy)
- Bugfix: getTodayRecord searches all months (cross-month boundary)
- WXML/WXSS unchanged; public API unchanged
2026-06-04 16:29:25 +08:00
lc ff2700c067 backup: snapshot before optimization 2026-06-04 16:25:43 +08:00