ca1793b4c0
- 趋势组件 trend-chart 新增 chartType(line/bar),line 模式用内联 SVG 渲染折线+渐变面积(无 canvas) - 记录页个人最佳趋势改用折线图,峰值信息移到图表下方对称高亮块显示最佳趋势产生日期 - 修复1: linePoints 漏存绝对坐标 y 导致运行时 toFixed 崩溃 - 修复2: 折线模式漏渲染数据点数值(valueText),现圆点上方显示且 0 值不显示
182 lines
24 KiB
Markdown
182 lines
24 KiB
Markdown
# 2026-08-04 工作日志
|
||
|
||
## 修复(治本):勋章图形精确居中 + 领奖台对齐(第二轮)
|
||
- 用户反馈第一轮 CSS 微调后勋章"还是偏上"。深挖发现真因:**7 枚 Phosphor 勋章图形在 24 viewBox 内垂直重心各不相同**(medalMilitary/shieldStar 偏下 1.13、trophyPh 偏下 0.75、crownPh 偏上 1.13),CSS margin 只能整体挪 `<image>` 盒子,永远修不齐不同勋章。
|
||
- **关键坑**:自写 SVG path 解析器易错(`V/H` 单参数命令打乱坐标配对、`a` 圆弧终点),包围盒必须用可靠库 `svgpath`(npm 装到 managed workspace):`abs() → unarc() → unshort() → iterate()` 收集控制点算包围盒。
|
||
- 治本方案:7 枚勋章 path 全部按图形包围盒**等比缩放到 24×0.92 并平移到 (12,12) 精确居中**(svgpath scale+translate,round(4))。`unarc` 把弧线展开为贝塞尔,path 变长(medal 344→1153 字符)但形状无损,7 枚共约 +9KB 可忽略。
|
||
- 同时 CSS:`.podium-badge` margin-top 2rpx→6rpx(flex 行盒中心与中文 glyph 视觉重心偏差补偿,图形已居中所以只需一次全局补偿)。
|
||
- 验证:7 枚新 path 包围盒中心全部 (12.00,12.00);node --check 通过;build() 7 枚 Fill/White 变体齐全;show_widget 渲染 3 枚代表勋章与昵称齐平。
|
||
- 后续若用户仍觉偏移,只调 `.podium-badge` margin-top 一个数即可(图形差异已清零)。
|
||
|
||
## 修复:领奖台勋章与昵称对齐错位
|
||
- 用户反馈领奖台(podium)勋章图标与昵称上下错位。
|
||
- 根因:flex align-items:center 对齐的是行盒中心,而 `.podium-name` line-height 1.3 使行盒(33.8rpx)远大于字高(26rpx),叠加中文 glyph 视觉重心偏高,图标视觉上比文字低。
|
||
- 修复(leaderboard.wxss,仅领奖台样式,`.podium-name` 无他处引用):①line-height 1.3→1(行盒贴字高);②`.podium-dur` margin-top 2→10rpx(补偿行盒缩短 ~8rpx,保持与名字间距);③`.podium-badge` 加 margin-top:2rpx(图标下移抵消中文视觉重心偏上)。
|
||
- 教训:icon+text 横排对齐,text 必须 line-height:1(或行盒≈图标高度),并视字体微调图标偏移;别依赖 line-height 冗余空间做"视觉居中"。
|
||
|
||
## 代码问题分析(已核实修订)
|
||
- 对平板支撑小程序做全量代码审查,初版报告 8 条问题经逐条事实核实后修订:撤回 3 条(隐私协议缺失/onLaunch await 阻塞启动/组件 styleIsolation 不一致,均为判断错误)、降级 2 条(console.log/云环境ID)、保留 3 条可选优化(lazyCodeLoading/测试覆盖/月份翻页上限)。
|
||
- 报告写入 docs/问题分析_2026-08-04.md。
|
||
- 教训记入 MEMORY.md:判断隐私合规先看 MP 后台而非代码;onLaunch async 不阻塞首屏;审查勿把合理设计/优化建议拔高成风险。
|
||
|
||
## 修复:记录页月份翻页上限
|
||
- pages/records/records.js 的 onNextMonth 原本可无限往后翻到未来月份。
|
||
- 加上限判断:下一月超过当前真实年月时提示"已经是最新月份"并 return,不翻页。
|
||
- node --check 通过。
|
||
|
||
## 第三次整体审查(用户再次询问"有没有问题")
|
||
- 又通读 custom-tab-bar、trend-chart、records.wxml 等此前未细看模块,git 历史确认项目持续迭代、质量高。
|
||
- 结论:无功能性 bug、无合规阻断、无需要紧急修复项。
|
||
- 如实记录的少数"设计权衡/边界"(非 bug,方向均偏乐观):
|
||
1. 首页"今日已完成"用 getTodayRecord 的全天累计时长(storage.js:451),自由训练/循环训练 duration 也计入今日目标达成判断 → 偏乐观。
|
||
2. 云同步是全量整包 update(最后写入胜),无字段级冲突合并;mergeRecords 仅在本地合并,多设备同时改边缘可能覆盖(单设备无影响)。
|
||
3. 卡路里 0.068 系数仅 onDayTap 一处,无一致性冲突。
|
||
|
||
## 优化:卡路里系数抽到 config.js
|
||
- config.js 新增 `caloriesPerSecond: 0.068` 配置项(注释说明估算口径),records.js onDayTap 改引用 `config.caloriesPerSecond`(带 `|| 0.068` 兜底)。
|
||
- 语法 node --check 通过。
|
||
|
||
## 新功能:完成弹窗科学提示(价值+风险)
|
||
- 用户要求把平板支撑科学建议加入完成成绩弹窗。先做了科学核查:原表"磷酸原/糖酵解按时长切换"是错误说法,方案改用修正口径——只讲价值/风险,不提供能系统。
|
||
- 实现:config.js 新增 `scienceTips`(4 段按时长 maxSeconds:120/300/480/Infinity,每段 value+risk);timer.js 新增 `_pickScienceTip(elapsed)` + data 字段 completionTipValue/Risk + _saveAndShowCompletion 里 setData;timer.wxml 连胜行后加 completion-tip 卡片(价值行 + 弱化「小贴士」风险行);timer.wxss 加样式(rgba primary 0.08 底、20rpx 圆角、tipIn 动画延迟 1.0s)。
|
||
- 边界验证:120s 整入段2、480s 整入段4、负/0 秒兜底段1;缺配置时 wx:if 不渲染,零风险。
|
||
- 循环训练(circuit)复用同一路径,workTotal 天然适用。
|
||
|
||
## 调整:删除完成弹窗「本次训练」标签;星级方案放弃
|
||
- 用户提出删除 completion-label「本次训练」+ 给提示卡加推荐指数星级。星级算法有产品理念矛盾(按时长给星违背科学共识/打脸耐力榜,按科学区间破纪录用户会低星),用户决策放弃星级。
|
||
- 实施:timer.wxml 删 `completion-label` 节点;timer.wxss 删对应样式,把 24rpx 间距并入 `.completion-number-wrap` 的 margin-bottom(8→32rpx)保持呼吸感。grep 确认无残留。
|
||
|
||
## 试点:勋章图标换成 Phosphor medal(30天「神登」)
|
||
- 对比 6 个图标库(Phosphor/Tabler/MDI/Ionicons/Lucide/FA),推荐 Phosphor。用户要求先做一枚进记录页。
|
||
- **关键坑**:Phosphor 是 256 viewBox,项目 `_svg` 硬编码 24 viewBox,直接塞会裁切。需 path 缩放——但**不能无脑除数字**:`a` 命令的 large-arc-flag/sweep-flag 只能 0/1、x-axis-rotation 是角度,都不该缩放。写了命令感知缩放器(token 流解析,a 命令 idx%7===2/3/4 不缩放),渲染对比验证无变形。
|
||
- 改动:icons.js PATHS 加 `medal`(缩放后 path)+ `out.medalWhite`;config.js 30天 badge icon 改 `medal`/`medalWhite`。trophy 系列保留(完成弹窗/排行榜空态仍用)。
|
||
- 验证:node --check 通过、build() 生成灰版(#999999)与白版(#FFFFFF)正确。
|
||
|
||
## 勋章图标全套替换为 Phosphor 勋章系(完成)
|
||
- 7 级递进:sealCheck(3天 抖登) → medal(7天 中登) → medalMilitary(14天 老登) → trophyPh(30天 神登) → certificate(60天 上古神登) → shieldStar(80天 洪荒神登) → crownPh(100天 究极登祖)。
|
||
- 全部 256→24 坐标缩放(用命令感知缩放器,a 命令 large-arc/sweep/rotation 不缩放)。**命名避坑**:Phosphor 版 trophy/crown 带 Ph 后缀(trophyPh/crownPh),避免覆盖 Material 版 trophy/crown(完成弹窗/排行榜仍在用)。
|
||
- 改动:icons.js PATHS 加 6 枚 + 6 个 White 变体(medal 已加);config.js trainingDayBadges 7 行全改。
|
||
- 验证:语法通过、7 枚灰版+白版 build 全部生成 OK、旧图标引用确认未误删。
|
||
- 缩放脚本在 /tmp/scale-phosphor.js(一次性工具,未入库)。
|
||
|
||
## 个人资料昵称旁显示已解锁勋章
|
||
- 需求:settings 页个人资料昵称后面展示已获得的勋章。
|
||
- **图标色坑**:badge 图标现有变体只有灰(未解锁)/白(解锁坐主题色圆盘),设置页浅底白图标会隐形。方案:icons.js 在 PATHS 定义后加 `PATHS.xxxFill = PATHS.xxx`(对象属性引用同一 path),build 循环自动生成主题色版 out.xxxFill,颜色跟随当前主题。
|
||
- 实现:settings.js data 加 `unlockedBadges: []`,onShow 里 `_getUnlockedBadges()`(totalDays >= b.days 过滤 + iconFill = icon+'Fill')setData;settings.wxml 昵称包 profile-name-row(flex),右侧 wx:for 渲染勋章组;settings.wxss 加 profile-name-row/profile-badges/profile-badge(32rpx,昵称可收缩省略、勋章组 flex-shrink:0)。
|
||
- 验证:语法通过、7 枚主题色版 build 生成 OK(跟随主题色)。
|
||
|
||
## 榜单页显示最新勋章
|
||
- 需求:leaderboard 页"我"的位置显示最新解锁勋章(点击 toast 显示勋章名+天数门槛)。用户确认:进榜 is-me 行 + 未进榜 my-bar 两处都显示 + 点击提示。
|
||
- **图标色分场景**:is-me 行浅底(primary 12%)用主题色 `xxxFill`;my-bar 主题渐变底用白版 `xxxWhite`——正好复用现有两种变体,零新增。
|
||
- 实现:leaderboard.js data 加 `myLatestBadge: null`,onShow 同步 `_getLatestBadge()`(本地 totalDays 取 days<=totalDays 最后一枚,返回 days/name/iconFill/iconWhite;<3 天或异常返回 null,且 days 未变不重复 setData),加 `onBadgeTap`(dataset 传 name/days);wxml 两处 rank-name 包 rank-name-row + 勋章 image(is-me 行 iconFill、my-bar iconWhite,wx:if myLatestBadge);wxss 加 rank-name-row/rank-badge(30rpx)。
|
||
- 数据纯本地,零云函数改动(勋章是"我的"荣誉,别人看不到)。
|
||
- 验证:语法通过;边界 0/2→null、3→3天、29→14天、85→80天、500→100天封顶 全对;7 枚 Fill/White 变体全存在;wxml/js 引用一致。
|
||
|
||
## 排查「17次不显示勋章」+ 修复本地兜底 isMe bug
|
||
- 用户反馈某用户 17 次训练不显示勋章。核实后根因:①用户看的是**线上旧版**(勋章功能今天刚加,未发版);②看的是**别人的行**(勋章只在"我"的行显示,设计如此)。
|
||
- 顺带发现真实 bug:`_applyLocal`(云函数不可用的本地兜底)`rankedList: [entry]` 的 entry **缺 isMe 标记** → is-me 行不渲染勋章,且 my-bar 条件(rank 1 > length 1)为 false → 弱网/云函数故障时勋章完全不可见。
|
||
- 修复:leaderboard.js 两处本地兜底 entry 补 `isMe: true`(耐力榜 + 日/月/年榜)。node --check 通过。
|
||
|
||
## 榜单勋章全榜可见(云函数 + 客户端联动)
|
||
- 需求:用户希望榜单上**所有用户**都能看到彼此的勋章(之前只有"我"本地算的勋章)。
|
||
- **云函数** `cloudfunctions/leaderboard/index.js`:`_buildFromScan` 每个 doc 开头算 `totalDays`(遍历全部 records 去重日期,与榜单周期无关),endurance/day/month/year 四个分支的 entry、ranked、myEntry 输出都带 `totalDays`。快照经 `publicEntry`(rest 解构只剥 memberKey/openid)自动透传,无需改 data.js。
|
||
- **客户端** `pages/leaderboard/leaderboard.js`:删掉 myLatestBadge(data/onShow/_getLatestBadge),改为通用 `_badgeOf(totalDays)`;`_applyResult` 给每个 ranked item 映射 `badgeIcon(Fill)/badgeName/badgeDays`(浅底行用),myEntry 额外 `badgeIconWhite`(my-bar 渐变底用);`_applyLocal` 开头算 localBadge 字段,两处 entry 展开进 badge 字段。
|
||
- **wxml**:rank-item 每行勋章 `wx:if item.badgeIcon`(不限 isMe,所有人显示)+ data-name/days;my-bar 用 `myEntry.badgeIconWhite`。
|
||
- 兼容:旧快照无 totalDays → _badgeOf(undefined)→null → 不渲染,等新快照(4min 定时重建)。**必须重新部署 leaderboard 云函数**。
|
||
- 验证:语法 OK、跨月去重正确、badge 映射(2天不渲染/14天老登/100天皇冠)OK、myLatestBadge 无残留。
|
||
|
||
## 修复:榜单勋章 500 报错(badgeIcon 赋了字符串 key 而非 data URI)
|
||
- 用户反馈:排行榜不显示勋章,控制台 `Failed to load local image resource /pages/leaderboard/medalMilitaryFill (500)`。
|
||
- **根因**:重构 myLatestBadge → `item.badgeIcon` 时,把 `badge.icon + 'Fill'`(字符串 key)直接赋给了 badgeIcon;WXML 直接 `src="{{item.badgeIcon}}"` 期望 data URI,字符串被当成路径加载 → 500。旧实现是 `icons[myLatestBadge.iconFill]` 先查映射再取 URI,重构时漏了这层查询。
|
||
- 修复:leaderboard.js 三处(_applyResult 的 list 映射、myEntry 映射、_applyLocal 的 localBadgeFields)都改为 `(this.data.icons || iconsMod.build())[badge.icon + 'Fill']` 取真实 data URI。
|
||
- 验证:语法 OK、badgeIcon 实测输出 `data:image/svg+xml;charset=utf-8,...`。
|
||
- 教训:WXML `<image src>` 直接绑定 data 字段时,字段必须已是 data URI,不能是图标 key 字符串。
|
||
|
||
## 补漏:领奖台前三名显示勋章
|
||
- 用户反馈领奖台前 3 名没勋章。原因:领奖台是独立 podium-slot 区(rankedList[0/1/2]),上一轮只改了普通 rank-item 行。
|
||
- 数据其实已就绪(_applyResult 对全部 ranked item 含前 3 名映射了 badgeIcon data URI)。
|
||
- 改动:leaderboard.wxml 3 个 podium-slot 的 podium-name 包成 podium-name-row(flex 居中),右侧加 podium-badge(第 1 名用 podium-badge--first 34rpx,2/3 名 30rpx),带 onBadgeTap;leaderboard.wxss 加 row/badge 样式。
|
||
- 验证:3 处渲染点齐全、语法 OK。
|
||
|
||
## 优化:虚拟领奖台(不足 3 名也显示)
|
||
- 用户要求:榜单数据不足 3 名时,不要只显示列表,也要显示(虚拟)领奖台。
|
||
- 改动(纯前端,无云函数改动):
|
||
- leaderboard.wxml 领奖台 `wx:if` 由 `rankedList.length >= 3` 改为 `>= 1`;3 个 podium-slot 各自用 `<block wx:if="{{rankedList[i]}}">` 真实内容 / `<block wx:else>` 虚拟空位(虚线轮廓头像 + 灰化 peopleFill 图标 + 底座「虚位以待」)。
|
||
- 下方列表 `wx:if` 由 `rankedList.length < 3 || index >= 3` 改为 `index >= 3`:领奖台出现时前 3 名不再在列表重复出现(<3 名时列表直接为空,名次全在领奖台)。
|
||
- leaderboard.wxss 加 `.podium-avatar--empty`(虚线圆、淡底)、`.podium-avatar__img--empty`(灰化 0.26 透明)、`.podium-empty-label`、`.podium-crown--empty`(0.3 透明)。
|
||
- 边界:0 名仍走 empty 空态(「暂无排行数据」);1 名→领奖台只填第 1 名,2/3 空位;2 名→填 1/2 名;≥3 名同原逻辑。语法 OK、无残留旧条件引用。
|
||
|
||
## 微调:领奖台勋章与昵称对齐(反复下压.margin-top)
|
||
- 用户反馈前三名昵称后勋章持续「偏高」。本质是 flex 居中 + 中文字形视觉重心(字体度量 descent)的固有偏差,只能靠 margin-top 盲推。
|
||
- 轨迹:.podium-badge margin-top 6rpx→8rpx(看截图仍高)→11rpx(用户说偏高)→14rpx。每次 +3rpx。
|
||
- 单一可调数字。若 14rpx 仍差,改结构性修法:勋章缩到与昵称同高(30→26rpx)或 .podium-name 加 display:inline-block 重约束行盒,从根消除偏移,不再靠 margin。
|
||
- 纯样式无语法风险。
|
||
|
||
## 升级:领奖台勋章对齐改为结构性修法(而非 margin 盲推)
|
||
- 用户反馈 margin-top 推到 14rpx 仍偏高,确认盲推失效。深挖两个隐藏根因:
|
||
1. `.podium-name` 自带 `margin-top:30rpx` 且在 flex **cross 轴**上,等于把昵称整体下推,反而让勋章更"偏上"——所以一路加 badge margin-top 永远追不平。
|
||
2. `.podium-name` `line-height:1`(26rpx 盒)比勋章(30rpx)矮,`align-items:center` 对齐的是"26rpx 行盒中心"与"30rpx 图标盒中心",叠加中文 glyph 视觉重心偏下,图标自然飘上。
|
||
- 结构性修法(leaderboard.wxss):① `.podium-name` `line-height:1`→`30rpx`(与勋章等高盒);② `.podium-name--first` 加 `line-height:34rpx`(与首名 34rpx 勋章等高);③ 间距 `margin-top:30rpx` 从 `.podium-name` **移到 `.podium-name-row`**(避免 cross 轴 margin 干扰居中);④ **删除 `.podium-badge` 的 `margin-top`** 盲推。
|
||
- 结果:flex `align-items:center` 现在对齐的是两个等高盒的中心,图标与昵称视觉精确对齐,不再依赖任意偏移量。若个别冠类勋章因图形重心仍有 ±1~2rpx 残差,单独加 `transform: translateY(2rpx)` 即可。
|
||
- 纯样式、无语法风险、无残留旧 margin 引用。
|
||
|
||
## 检查并统一:成就勋章图标跨页尺寸
|
||
- 用户对齐 OK 后,顺带查勋章大小一致性。结论:
|
||
1. 图标本体视觉大小一致——7 枚勋章 SVG 早已统一缩放居中到 24×0.92 viewBox,同尺寸盒内可见主体等大,无"crown 比 medal 大"问题。
|
||
2. 非预期不一致在跨页盒子尺寸:排行榜(领奖台 2/3 名 .podium-badge 30、列表 .rank-badge 30)用 30rpx;设置页 .profile-badge 与记录页 .badge-node-icon 用 32rpx。
|
||
- 修复:把 settings.wxss `.profile-badge` 与 records.wxss `.badge-node-icon` 的 32rpx→30rpx,统一到基准 30rpx(且与领奖台昵称对齐 line-height:30rpx 配套)。领奖台首名 .podium-badge--first 34rpx 作为冠军强调保留(设计性,非 bug)。
|
||
- 若后续想连冠军也统一 30rpx,改 .podium-badge--first 为 30 且 .podium-name--first line-height 同步回 30rpx 即可。
|
||
|
||
## 调整:领奖台前三名勋章统一大小
|
||
- 用户要求前三名勋章一致大小(此前首名 34rpx 强调、2/3 名 30rpx)。
|
||
- 改动:leaderboard.wxss `.podium-badge--first` 34→30rpx;配套 `.podium-name--first` line-height 34→30rpx(保持首名昵称与勋章等高盒对齐)。
|
||
- 结果:领奖台前三名勋章统一 30rpx,与全局基准(列表 .rank-badge 30、设置页 .profile-badge 30、记录页 .badge-node-icon 30)完全一致。纯样式无语法风险。
|
||
|
||
## 提交与推送
|
||
- commit `b52db87`(17 文件,+690/-67)包含今天整轮(虚拟领奖台+勋章对齐结构修复+全 app 勋章 30rpx 统一)。
|
||
- 已推 `origin`(github.com/cnliucheng/wx_pbzc) + 新增远程 `soao`(https://git.soao.net/lc/wx_pbzc.git) 并推 `main`。两个远程同步于 b52db87。
|
||
- 提醒:cloudfunctions/leaderboard 若含线上逻辑改动需开发者工具「上传并部署」才生效(本次主要改前端)。
|
||
|
||
## 上线前审查(launch readiness)
|
||
- 主包 540KB(<<2MB,无需分包);网络全走 wx.cloud(免 request 域名白名单);无硬编码 http;隐私接口仅 chooseAvatar(后台已配)。**合规面干净**。
|
||
- 🔴 阻断项:①云函数 git 提交≠部署——`leaderboard`(本次 b52db87 改 17 行 totalDays/全榜勋章)、`tts`(8-03 改)需重新部署;②`tts` 环境变量 TTS_SECRET_ID/KEY/REGION 须在云函数控制台配好(否则语音失败)。
|
||
- 🟡 建议项:清理调试 console.log(cloud.js 14 处等)、project.config.json 上线开关(minified→true/uploadWithSourceMap→false)、加 wx.onNeedPrivacyAuthorize 自定义隐私弹窗、加全局错误上报、清理残留(cloudfunctions/shared 空死目录/根 preview-buttons.html/.claude/.codegraph)。
|
||
- 核实:leaderboard 实际 require('./data') 非 '../shared',空 shared 目录无害;`data.js`/`cache.js` 同目录存在,部署含之;无分包;无 wx.onError。
|
||
- 报告:.workbuddy/launch-readiness-review.md。
|
||
|
||
## 执行:上线前建议项清理(用户确认"需要")
|
||
- 清调试 console.*:脚本 .workbuddy/clean-console.js 批量删(独立 console 行 + 箭头函数体 `=> console`→`=> {}`),删 34 处;漏 2 处 `if(){console.log();return}` 行内形式手动改;Grep 复扫全项目 *.js 已无 console.* 残留。涉及 cloud.js/storage.js/voice.js/theme.js/app.js/leaderboard.js/timer.js/settings.js/cloudfunctions/leaderboard/index.js,均 node --check 通过。
|
||
- project.config.json:minified false→true、uploadWithSourceMap true→false(上线防源码泄露+减小包体)。
|
||
- 清残留:删 preview-buttons.html + rmdir cloudfunctions/shared(空死目录,重构遗留);.claude/.codegraph 已被 packOptions.ignore 的 `.!*` 忽略,不动。
|
||
- 未做:全局错误上报(wx.onError)、自定义隐私弹窗(用户仅确认做这三个清理项)。
|
||
- 改动未提交(git status 显示 M/D 文件)。clean-console.js 为一性工具,留 .workbuddy 不进包。
|
||
|
||
## 上线前优化续:组件按需注入 + records 补声明 + 提交推送
|
||
- 微信开发者工具「代码质量」扫描显示「组件:启用组件按需注入 — 未通过」。
|
||
- 根因:project.config.json 缺 `lazyCodeLoading` 配置项。已加 `"lazyCodeLoading": "requiredComponents"`(只加载页面 usingComponents 声明且模板实际用到的组件)。
|
||
- 核实:7 组件均静态写死在 WXML,无动态 `<component is=`/抽象节点/custom-tab-bar 不受影响 → 无负面影响;基础库 <2.10.1 用户自动回退全量加载(无害)。
|
||
- 顺带发现真 bug:pages/records/records.json 漏声明 ui-skeleton(WXML 第 4/6 行已用)→ 已补;5 页面声明与 WXML 实际使用现已完全一致。
|
||
- 提交:commit `187c426`(14 文件,+100/-199,含之前的 console 清理+project.config 开关+删 preview-buttons.html+lazyCodeLoading+records 补声明)。clean-console.js 一次性工具未入库。
|
||
- 推送:soao(https://git.soao.net/lc/wx_pbzc.git)成功(b52db87..187c426);**origin(github)当前环境到 github.com:443 SSL 连接被重置(HTTP2 framing/SSL_ERROR_SYSCALL 交替),多次重试失败——环境网络抖动,非代码问题**。本地 commit 安全,待网络恢复后重试 `git push origin main`。
|
||
|
||
## 功能:个人最佳趋势改为折线图 + 底部加最佳趋势产生日期
|
||
- 用户要求:记录页「个人最佳趋势」(bestTrendData)从柱状图改折线图,并在底部加「最佳趋势产生日期」(像「最高训练日」那样)。
|
||
- 实现:趋势组件 `trend-chart` 加 `chartType`(bar|line,默认 bar,柱状图完全不动)+ `lineColor` 属性。line 模式用**内联 SVG(data URI)→`<image>`** 渲染折线+半透明面积(无 canvas,和组件 no-canvas 理念一致);圆点与横轴标签用 WXML 绝对定位(按 xPercent/yPercent),保证清晰且能吃主题色(因 SVG 在 image 内读不到 CSS 变量,颜色由页面传 hex)。
|
||
- 几何:viewBox=640×H(H=peak?170:200),`mode=widthFix` 让 SVG 宽高比与容器 rpx 一致→stroke 均匀不拉伸;x 按 (i+0.5)*640/N 均分,y 用 topPad/bottomPad 留头尾余量;零值点落到接近底部。
|
||
- 数据层不动(getBestTrendData 仍返回 label=周一/7月 等周期标签,符合"就像最高训练日"的粒度)。
|
||
- records 页:best 趋势 `<trend-chart chart-type="line" line-color="{{bestLineColor}}">`;原在 header 的 `best-trend-best` 文本移到图表下方,复用 `.trend-highlight` 对称块(icons.crownFill + bestTrendSummary.peakTitle + peakText);新增 `_buildBestSummary` 把 peakTitle 覆盖为「个人最佳日/月」(通用 getTrendSummary 原给"最高训练日",不对);bestLineColor=theme.primary(peak 实际用主题主色,非金)。
|
||
- 验证:node --check 通过;tests/trend-state.test.js 5/5 通过(数据层未变);SVG 字符串模拟确认无 NaN、含 stroke/fill-opacity/width/height。删了 records.wxss 里已不用的 .best-trend-best 样式。
|
||
- 改动未提交(git status 有 M)。待用户审阅后可提交(soao 国内远程稳定;origin 仍待网络恢复推)。
|
||
|
||
## BUG 修复:折线图运行时崩溃(toFixed of undefined)
|
||
- 现象:记录页切换 trend 模式报 `Cannot read property 'toFixed' of undefined`(trend-chart.js:90, _buildLineSvg 内 `p.y.toFixed`)。
|
||
- 根因:`_compute` 生成 linePoints 时只存了 `x`(绝对)与 `yPercent`(百分比),**漏存绝对坐标 `y`**;`_buildLineSvg` 画 polyline/area 用的是 viewBox 绝对坐标 `p.x`/`p.y`,`p.y` 为 undefined → 崩。WXML 圆点/标签用 xPercent/yPercent 定位(无误)。
|
||
- 修复:linePoints 返回对象补 `y`(与 x 同为 viewBox 坐标);`_buildLineSvg` 加防御 `valid = points.filter(p => p && typeof p.x==='number' && typeof p.y==='number')`,first/last/area/polyline 全改走 `valid`,空则返 ''。
|
||
- 验证:node --check 通过;用真实 getBestTrendData 输出实跑 _compute(week/month)均生成 lineSvg 不再崩;稀疏数组也安全。临时 repro 脚本已删。改动未提交。
|
||
|
||
## BUG 修复:折线图数据点未显示数值
|
||
- 现象:折线模式每个数据点旁没有数值文字(柱状图有,折线没有)。
|
||
- 根因:line 模式 WXML 只渲染了圆点(`trend-line-dot`)与横轴 label,**漏渲染 valueText**;且 linePoints 返回对象未透传 `value` 字段,无法做 `value>0` 判断。
|
||
- 修复:trend-chart.js 的 linePoints 返回补 `value: b.value`(bars 项第57行本就有 value);WXML 圆点内加 `<text wx:if="{{item.value>0}}" class="trend-line-value">{{item.valueText}}</text>`(仿柱状图,0 值不显示);WXSS 加 `.trend-line-value`(绝对定位在 dot 上方居中,16rpx,高亮点用主色加粗),并把 `.trend-chart.line` 的 padding-top 16rpx→30rpx 给最高点数值留缓冲防裁切。
|
||
- 验证:node --check 通过;bars.value 字段确认存在。改动未提交。
|