Files
wx_pbzc/.workbuddy/memory/2026-08-12.md
T
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

92 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-08-12 工作日志
## 循环训练页遮挡问题分析与 redesign 规划
- 读取 `pages/timer/timer.wxml/wxss/js`,定位循环训练态(circuit mode)布局。
- 问题根因:`.timer-page``flex column``min-height: 100vh` 但无滚动,中间圆环 420rpx + 多层呼吸环 488/620rpx + 顶部卡片 + 状态文字 + 目标卡 + 提示气泡的总高度在小屏/大字体下容易超过视口;底部 `.controls``margin-top: auto` 贴底,结果会被内容顶出可视区域或被安全区截断。
- 规划方案(未改代码):
1. 圆环从 420rpx 缩到 340rpx,呼吸环同步缩小。
2. 顶部卡片内嵌组进度条,组数/阶段/配置摘要合一,减少一层垂直空间。
3. 状态文字与圆环内副标题、目标卡与姿态提示错位排布,避免信息重复。
4. 底部控件固定高度 + `padding-bottom: calc(32rpx + env(safe-area-inset-bottom))`,保证始终在安全区上方可见。
5. 整体改为 `justify-content: space-between` 的 flex 布局,顶部-中部-底部三大块按可用空间分配。
- 已输出 SVG 线框图,待确认后再落地代码。
## 方案修正(用户反馈:timer 页是公用页面,仅循环模式有组进度条)
- 用户指出原规划把页面当"恒有顶部卡片"设计,切换模式重心会跳。
- 修订方案(未改代码):**组进度从独立顶部面板改为「圆环外圈分段弧」**——
-`progress-ring` canvas 里加 sets/currentSet/isResting 属性,track 环外侧画一圈分段弧(已完成=主色、进行中=主色+端点光点、未开始=浅灰、休息时下一段=success 绿)。
- 单组/自由模式不传 sets → 不渲染分段弧,页面结构与现状完全一致,零影响。
- 圆环内副标题循环模式显示「第 X/Y 组」,单组显示「目标 X」。
- 组数 >15 时退化为圆环下方细线进度条。
- 顶部 circuit-bar 面板(wxml 20-53 行、wxss 15-225 行)整个删除,垂直空间全部还给圆环区与底部控件,从根上解决遮挡。
- 已确认 `components/progress-ring` 为 canvas 2d 实现(_draw() 内 ctx.arc/stroke),扩分段弧同套 API,可行。
## 落地:循环训练组进度改造(用户批准后实施)
- **`components/progress-ring/progress-ring.js`**
- 新增属性 `sets/currentSet/resting/successColor`sets<=0 时零渲染,单组/自由模式不受影响)。
- 新增 `_drawSetArcs(pulse)`:track 环外侧画分段弧(arcR = radius + ringWidth/2 + 3rpx,弧宽 8rpx,段间隔 2.5°)。三态:已完成=primaryColor、进行中=primaryColor+端点光点、休息时下一段=successColor('#00B578'),未开始=trackColor。
- 呼吸动画用 `canvas.requestAnimationFrame` 循环(周期 1.6s,sin 相位),只清外圈环带(clip 环形避免碰内圈倒计时弧);paused 时冻结为静态;`detached` 时 cancel。
- `_draw()` 末尾补调 `_drawSetArcs(_setPulsePhase || 0.6)`,保证每秒全量重绘后分段弧仍在。
- **`pages/timer/timer.wxml`**:删除整个 `circuit-bar` 面板(原 18-53 行);`<progress-ring>` 新增 `sets="{{totalSets}}" currentSet="{{currentSet}}" resting="{{isResting}}"`
- **`pages/timer/timer.js`**:删除 `circuitDots/circuitShowDots/circuitTotalWork/dotsDone/dotsActive/dotsNext` 字段与 DOTS_MAX 点阵构建;onTick 由 dots* 改为 `ringSubText: 第 X/Y 组`_initCircuit 的 ringSubText 改为 `共 X 组 · 休息 Y 秒`rest=0 省略休息段),goalLine 保持 `每组 X · 共 Y 组`
- **`pages/timer/timer.wxss`**:删除全部 circuit 样式(.circuit-bar/.circuit-dots/.circuit-track/.circuit-meta/.circuit-count/.circuit-phase/.circuit-sub 等)。
- **落地时的设计决策**:组数上限 50(_int clamp),环形 360° 空间充裕,50 段也不挤线(旧 DOTS_MAX=15 是横向卡片宽度受限),故**不做数量降级**;原方案"组数>15 退化线性条"在环形下无必要。
- 验证:node --check 通过;grep 无残留代码引用(仅注释说明文字)。
## 呼吸环淡化(用户反馈"圆线条太明显")
- `timer.wxss``.breath-aura`border 6rpx/0.55 → 4rpx/0.20box-shadow 外层 40rpx/0.45 → 30rpx/0.22、内层 28rpx/0.22 → 20rpx/0.10auraBreathe 透明度 0.55↔0.85 → 0.30↔0.50fast 版 0.6↔0.9 → 0.34↔0.55。
- `.breathe-ring` 三档径向渐变强度:0.20/0.26/0.34 → 0.13/0.17/0.22,柔光更淡雅,不与倒计时环抢视觉。
## 目标卡与提示气泡轻量化(用户反馈"两个提示框不好看")
- 问题:`.goal-card` 是白底卡片+右箭头,看起来像可点按钮但无 tap;`.timer-tip` 是白底气泡+左侧绿条+上方小三角+呼吸阴影,与目标卡叠在一起视觉噪音大。
- `timer.wxml`:删除 `.goal-card` 中的右箭头 `goal-arrow`
- `timer.wxss`
- `.goal-card` 改为轻量胶囊标签:`inline-flex`、主色 8% 淡底、无边框无阴影、圆角 999rpxpadding 24→14rpx/24rpx;图标 40→32rpx;文字 28→26rpx、权重 600→500、主色。
- `.timer-tip` 改为药丸标签:去掉 `border-left`、小三角、box-shadow、tipPulse 呼吸动画;背景主色 8% 淡底(done 态 success 10%);padding 20/32→12/24rpx;圆角 999rpx;图标 40→30rpx;文字 30→26rpx、权重 600→500。
- 验证:grep 无 `goal-arrow/tipPulse/timer-tip::before/border-left: 8rpx` 残留。
## 目标卡 + 提示气泡合并为单气泡(用户反馈"字体小了、能否合并、页面三模式公用")
- 新结构 `.info-bubble`timer.wxml/wxss):一张主色 8% 淡底圆角卡,两行——
-`info-line--goal`target 图标 + goalLine26rpx/500/主色(静态摘要,常驻)
- 分隔线 `info-divider`(1rpx 主色 14% 淡线,仅提示出现时渲染)
-`info-line--tip`tipIcon + runningTip30rpx/600/`--text`(动态提示,比目标行大一号突出);`--done` 态 success 绿
- 三模式共用同一容器:单组/自由/循环都走 info-bubble;循环休息/暂停时 runningTip='' → 分隔线与提示行整体消失,气泡自动收缩只留目标行,布局不跳。
-`.goal-card/.goal-icon/.goal-text/.timer-tip/.timer-tip-icon/.timer-tip-text` 全部删除,grep 无残留。
## 状态文案并入信息气泡(用户反馈"撑住"等硬编码文案能否整合进气泡)
- 背景:环下方 `.timer-status`statusText:准备开始/撑住/休息中/已暂停)是独立一行,用户希望圆环下只留一张卡。
- `timer.wxml`:删除 `.timer-status` 行,气泡改为三行结构——上 `info-line--status`(小圆点 + statusText+ 恒显分隔线 + 中 `info-line--goal` + 提示行(条件渲染)。
- `timer.wxss``.timer-status` 样式删除,新增 `.info-line--status/.info-status-dot/.info-status-text`
- 状态行 32rpx/700,小圆点 14rpx 用 `background: currentColor` 跟随状态色(纯 CSS,规避 SVG 图标烤死问题)。
- 配色:`status--running`=主色(圆点呼吸 1.6s);休息时 `status` 字段仍是 running,靠 `isResting` 追加 `info-line--rest` 覆盖为 success 绿(呼吸 1.8s);`status--paused/idle`=text-secondary 灰,paused 圆点冻结动画。
- `.info-bubble` margin-top 24→40rpx(承接原 timer-status 间距)、padding 20→24rpx。
- 关键机制备忘:**resting 时 status 字段值仍是 'running'**,状态行转绿必须靠 `isResting` 单独加类,不能只看 status。
- 验证:grep 无 `timer-status` 代码残留(仅注释文字),js 未改动。
## 进度弧"0 点对齐"问题:两轮修复被否定,已全部回滚(待用户澄清)
- 用户反馈(两次截图):训练时粗进度弧起点与 0 点/顶部起点差一点没对齐,运动过程中更明显(循环与单组模式都出现过)。
- 尝试过两轮修复(progress-ring.js `_drawSetArcs` 半径/清除区微调),用户判定"完全理解错了",**要求撤销**。
- 已回滚:`git diff` 确认 progress-ring.js 与 HEAD`05c4763` 分段弧初始实现:glowPad=6、arcR=radius+lw/2+3、arcW=8、清除区 clip 内缘 arcR-band)完全一致,`node --check` 通过。
- 教训:对齐类问题不要凭数值推理直接改半径,先让用户明确"0 点"的参照物(刻度环/呼吸环/分段弧?)与出现模式,再定位。
- **最终定位与修复(用户澄清"所有运动中,进度弧零点与表盘 0 点没对齐")**:
- 根因确凿:`_drawSetArcs` 每段起点 `+gap/2`(1.25°),**外圈分段弧第一段从 12 点偏右 1.25° 开始**(半径 ~207dpr 处 ≈ 4.5dpr ≈ 1.5px),而内圈进度弧/12 点长刻度都从精确 -π/2 开始 → 循环模式外圈与内圈 0 点肉眼错开。
- 修复:`a0 = startAngle + (i-1)*segAngle`(第一段精确 -π/2 起),`a1 = a0 + segAngle - gap`(段尾留 gap)。段间空隙均匀(2.5°×3),收尾空隙落在 12 点左侧,环带以 12 点为起点。node 验算:段起点 270°/30°/150°,空隙 2.5° 均匀,首段 12 点 ✓。
- 单组/自由模式无分段弧,canvas 内刻度/进度弧同基准(-π/2),数学对齐;若用户仍反馈错位需再查(可能涉及 canvas 布局/参照物)。
- 注意:`gap/2` 对称偏移是"段内居中空隙"的常见写法,环形进度环带与刻度基准对齐时必须从 -π/2 起算。
- **用户叫停("算了,这个问题先不修复了")**:零点对齐问题整体搁置。该轮 progress-ring.js 的角度修复(仅影响循环模式、覆盖不了单组模式现象)已 `git checkout` 回退,与 HEAD 一致。等用户想继续时再排查,方向可能是 canvas 布局/参照物而非半径。
## 新功能:训练时长低于阈值不记录(config.minRecordSeconds,默认 20 秒)
- 需求:训练有效时长 < 20 秒(可配置)不写入记录,并给用户明确提示;阈值收进 config.js。
- **`config.js`**:新增 `minRecordSeconds: 20`(带注释:不写记录、不更新连胜;循环按有效撑持秒数=各组时长之和判断)。
- **`pages/timer/timer.js`**
- `finishTraining()``elapsed >= minSec` 才播完成语音(低于阈值不庆祝)。
- `_onCircuitComplete()`:循环自然完成路径同样按 `workTotal >= minSec` 播语音。
- `_saveAndShowCompletion(elapsed)` 开头加**阈值兜底**`elapsed < minSec``_showNotRecorded(elapsed, minSec)` 直接 return。手动结束与循环自然完成两条路径都汇聚到这里,任何入口都不会把短时训练落库。
- 新增 `_showNotRecorded(elapsed, minSec)`:复用完成弹窗(避免系统原生 modal 在 WebView stacking context 下 hit-test 不稳),不保存记录/连胜、无 confetti/streak/科学提示,大数字照常 countUp 到 elapsed;置 `completionNotRecorded: true``minRecordSeconds: minSec`、标题"未达最低记录时长"。
- data 新增初始字段 `completionNotRecorded: false``minRecordSeconds: 20`
- **状态残留坑(已修)**`onTrainAgain`(再来一次)与 `_saveAndShowCompletion` 正常分支都必须显式 `completionNotRecorded: false`,否则上轮未记录后重练,下次正常完成弹窗会误显示"未计入记录"且隐藏分享/记录按钮。
- **`timer.wxml`**:完成弹窗新增 `.completion-not-recorded` 提示块(infoFill 图标 + "本次训练未计入记录" + 副行"撑满 X 秒以上才会记录并计入连续打卡");未记录态 `wx:if="{{!completionNotRecorded}}"` 隐藏"查看记录/分享"(没有成绩可看/可晒),仅留"再来一次 + 回到首页"。
- **`timer.wxss`**:新增 `.completion-not-recorded` 主色淡底信息块(与 completion-tip 同风格,tipIn 延迟 0.5s 入场)。
- 保留逻辑:`elapsed < 3` 秒仍走 toast「训练时间太短」+ navigateBack(几乎未开始,不弹完成弹窗)。
- 验证:node --check 通过;grep 确认 minRecordSeconds/completionNotRecorded/_showNotRecorded 三处字段在 config/js/wxml 引用一致。