Files
wx_pbzc/.workbuddy/memory/2026-08-12.md
T
lc b6d94b21cd fix(timer): 分段弧光点居中置顶 + 拉大与进度弧间距
- 光点移到段中点(am=(a0+a1)/2),两端粗细对称;重构为两遍绘制,
  光点统一后绘浮于所有弧之上,不再被相邻圆头吞掉;加大加亮成珠状
- glowPad 6→18 与 _drawSetArcs pad 同步,arcR 外移 3→14,
  分段弧与进度弧间距 -1 → +10dpr(size=420),呼吸光环不重叠
2026-08-12 10:34:54 +08:00

109 lines
15 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 引用一致。
## 分段弧两端粗细不一致(已修)
- 用户反馈:循环训练时分段弧"两端粗细不一致"。
- 根因(progress-ring.js `_drawSetArcs`):发光光点坐标固定取段尾角 `a1``dx=cx+arcR*cos(a1)`),当前段(active)/休息预告段(next)的尾端 = 光点+8dpr 发光晕(直径≈弧宽+),首端却只是 `lineCap:'round'` 普通圆头 → 同段弧尾粗头细。已完成/未开始段两端都是普通圆头,粗细一致,所以现象集中在运动中那一段。
- 修复:光点移到**段中点** `am=(a0+a1)/2`(3 行),两端自然对称,光点仍作"当前组"标记。node --check 通过。
- 注意:若以后想给分段弧加"当前组跟随倒计时移动"的进度感,光点可改为随剩余时间在段内插值,但需先确认用户是否要这个效果。
## 分段弧间距 + 光点置顶(用户反馈"两弧太近、弧压着光点")
- 用户反馈两点:①分段弧与进度弧距离太近;②光点被分段弧压住(视觉上弧盖着光点)。
- **间距修复**progress-ring.jssize=420 时验证):
- 根因:间距 = gap arcW/2 = 34 = **−1dpr(重叠 1)**。因为分段弧 arcR 仅比进度弧外缘靠外 3dpr,而弧半宽 4dpr。
- `_draw()``glowPad` 6→14dpr(进度弧半径内缩 8,给外圈腾空间);`_drawSetArcs()` 的 radius pad 6→14**两处必须同步**,已加注释)且 arcR 间距 `+3→+9dpr`。结果:进度弧外缘 204→196、分段弧内缘 203→201,间距 −1→**+5dpr**。副作用:单组/自由模式的进度环也内缩 ~8dpr(约 4%),中心数字区略小;进度弧尾端发光点 shadowBlur=12 阴影反而从"被 canvas 裁"变完整。
- 段间空隙 gap=2.5° 是段间距,**与环间距无关,不动**。
- **光点置顶**:原实现光点在逐段循环内、每段弧 stroke 之后画,理论上应在弧上,但视觉上被 round cap 相邻段边缘"吞掉"。重构为**两遍绘制**:pass1 只画所有弧并收集 emphasized 段光点(x/y/color),pass2 统一在所有弧之上画光点。同时光点加大加亮:dotR 从 `0.85~1.2×弧半宽``1.15~1.4×`alpha `0.55~1.0``0.7~1.0`,白芯 0.85→0.9,读起来像"珠珠骑在弧上"。
- 光点仍居段中点(沿用上轮两端对称修复);外缘 209dpr 不超 canvas 半宽 210,与 breath-aura(内缘 ~232)无重叠。
- 验证:node --check 通过;数值全部核算。未提交 git。
- **间距仍不够(用户反馈"还是太近")→ 再翻倍**canvas 半宽 210 是硬上限,剩余空间仅 ~5dpr,要明显拉开只能继续内缩进度弧。glowPad 14→18、arcR 外移量 9→14,间距 **5→10dpr**(进度弧外缘 196→192,分段弧内缘 201→202,光点外缘 211.6 超画布 0.8px 亚像素无感)。进度环直径累计缩 ~6%(408→384)。约束备忘:**间距 = arcR外移量 arcW/2,且 ≤ glowPad arcW margin**;想再拉开只能继续缩环或减弧宽。