按时间倒序展示烹饪会话(active / completed / cancelled / disconnected),每条卡片显示状态、设备/探针、目标/峰值/时长;熟度始终显示,但在“无 presetName 且 meatType=custom”的裸自定义温度场景下不显示肉种。;点击进入详情,长按删除(带确认)。
lib/features/thermometer/presentation/pages/cook_log_page.dart(338 行)cookLogProvider(持久化会话列表,addSession 新会话 prepend 到列表头部、超过 _maxCookLogSessions(50)截断末尾,见 待解决问题)、temperatureUnitProvider/cook-log(CookLogPage.routeName)lib/app.dart 静态 routes map若会话尚无峰值温度记录(peakTempF 为 null),底部 Peak 栏显示 —,而不是温度数值。
顶部返回 + 居中标题(来自本地化字段 cookLogTitle,并非固定英文 "Cook Log")。下方滚动列表:每个 _SessionCard 卡片左侧有按状态色(绿/红/黄/蓝)的 3px 竖条;顶行是 "Mar 15, 2026 · 3:42 PM" 日期 + 状态图标 + 状态文字(通过 localizedCookStatus 按当前语言本地化显示对应状态);中段大号文字 "肉种 · 熟度";下方一行显示设备名与探针颜色名;其中设备部分优先显示 session.deviceId,若为空则回退为本地化的未知设备文案(cookLogUnknownDevice),探针部分显示 session.probeNumber.colorName。底部三个 _StatChip:Target / Peak / Time。空列表显示居中提示文案。
IconButton.onPressed → Navigator.pop(context) → 返回 Dashboard_SessionCard.onTap → navigateInstant(context, CookLogDetailPage(session: session))CookLogDetailPage 接受 session 参数_SessionCard.onLongPress → _confirmDelete(context)cookLogDeleteTitle,正文来自 cookLogConfirmDelete;确认后调 cookLogProvider.notifier.deleteSession(session.id)GestureDetector.onLongPress
→ CookLogPage._confirmDelete(context)
→ showDialog<bool>(...)
→ 用户确认 → cookLogProvider.notifier.deleteSession(session.id)
→ SharedPreferences 持久化更新
→ 列表立即重建(少了这一项)
Navigator.pop(ctx, bool)另:非 mock 模式下,cookLogProvider 不再只是本地 SharedPreferences 列表;它会按账号做云端同步,并通过 cookLogRealtimeProvider 接收其他手机推送后触发拉取同步。因此同一账号下,其他手机新增/删除日志或修改备注后,本页列表也会在同步后更新。
另外,多手机同时参与同一烹饪会话时,cook log 不是每台手机都各写一条:被标记为镜像会话(remoteStarted)的手机在结束会话时会跳过本机写入,由发起该烹饪的那台手机持有单条日志记录,其余手机通过账号同步拿到这条记录,避免同一会话在各端重复出现。
watch:cookLogProvider(任何会话增删改重建)、temperatureUnitProvider(°C/°F 切换重建以更新数字)。
烹饪日志的写入来源主要是 CookingSessionsNotifier._finalizeById(处理 target-reached 后的状态机完成、app exit 等结束路径);hard kill / kill recovery 则是在 CookingSessionsNotifier._loadFromStorage() 中直接调用 cookLogProvider.notifier.addSession(done) 写入,并不经过 _finalizeById。烹饪页的 _finishSession 仅在用户手动取消(CookSessionStatus.cancelled)时调用;但写入 cook log 仍受 !active.remoteStarted 约束,镜像会话不会在本机重复写入。本页通常只读,页面上的直接用户操作只有长按删除;但在 mock 模式下,cookLogProvider 若发现日志为空,会自动写入 4 条 mock 会话并持久化。
无显著差异。
_months 是英文缩写常量(Jan/Feb/...),_formatTime 用 12 小时 AM/PM。其他多语言用户看到这里仍是英文 🔴 需要确认(应该改用 intl.DateFormat 配合 locale)。CookSessionStatus:英文枚举的 displayName 不一定走 ARB;同上。localizedCookStatus(l, status)(lib/core/utils/meat_localization.dart),按 active/completed/cancelled/disconnected switch 到 ARB key statusActive/statusCompleted/statusCancelled/statusDisconnected(6 语 en/zh/de/es/fr/it 翻译早已就位、本次只是接线);session.doneness 同次顺手从 .displayName 改为 localizedDoneness(l, ...)。⚠️ 15e7e6d / TAPD #1003132:cook-log 列表 + 详情页 doneness 渲染再换源到 localizedDonenessKey(l, donenessKeyForMeatTempF(session.displayMeatName, session.targetTemp, family: session.deviceId.boosterFamily))——session.doneness 在启动会话时硬编码 Doneness.medium、永不动,所以原 localizedDoneness(l, session.doneness) 让所有行都显示 "Medium";改后从肉表 + target 反查实际 band(Chicken 的 USDA Crispy 174–179°F 也能显示,5 项 enum 无此值)。已落历史会话同步生效。CookSessionStatus.displayName getter 本身保留作 dev-log / 调试用,UI 路径不再走它。