# 2026-08-07 ## 里程碑 tab 设计校正:时长维度改为「单次最长时间」 用户纠正先前理解偏差:时长里程碑要的是**单次最长时间(个人最佳)**,不是"首次突破 X 分钟"的阈值事件。 这其实与用户最初原话"什么时间单次坚持最长"一致;之前被带偏成 `first_duration` 阈值家族。 **校正后的家族(6 类):** 1. `first_train` 第一次训练 → min(record.date) 2. `badge` ×7 勋章首解锁(复用 config.trainingDayBadges)→ 第 N 个去重训练日=解锁日 3. `longest_plank` **单次坚持最久**(个人最佳)→ argmax(duration),取该记录日期+时长;**含循环**(circuit 的 record.duration=workTotal 已排除休息,公平)。属「个人最佳」类,与其余「第一次」类并列。 4. `first_streak` 第一次连续打卡 N 天 → 门槛 config.milestoneFirsts.streaks=[7,14,30] 5. 模式首秀:`first_circuit`、`first_plan` **config 变化:** `milestoneFirsts` 去掉 `durations`(不再有时长阈值);仅保留 `streaks:[7,14,30]`。 `longest_plank` 无需阈值配置,直接取全量记录 max(duration)。 **待定细节(已向用户提出):** `longest_plank` 是「1 个节点=当前历史最长(若被刷新则更新日期)」,还是「每次刷新纪录都记一个节点(PR 进阶时间线)」?默认按前者(最贴合"单次最长时间"语义)。 ## 顺带诊断:模拟器 vs 正式版连续打卡不一致 streak 是本地缓存计数器(`current_streak`),`validateStreak` 普通启动只信任旧 count、不重算;`recomputeStreak` 仅删记录/云端恢复时跑。模拟器与真机是两套隔离存储沙箱,且 streak 不随记录并集自动对齐 → 4天 vs 2天属预期差异。根治=启动即 `recomputeStreak()`。用户尚未批准改代码。