WHIP 个人健康 OS
围绕每天的记录,设计一个本地优先的健康空间。复盘从空白状态到 IndexedDB,再到 PWA 离线与数据恢复的完整路径。

留在本地。
一次录入、按日回看,
明确保存与恢复的边界。
实际移动端界面,原色呈现;合成 QA 示例记录。
项目背景与挑战Context
WHIP 围绕日常健康记录展开:饮食、饮水、运动、身体状态与睡眠频率不同,却需要在同一天被查看。目标用户设定为希望自己保管记录、愿意持续输入日常信息的个人用户。
设计假设是:降低每次录入的步骤,比在首屏堆积更多指标更有价值。因此先把入口安排成今日、饮食、运动、趋势与我的五个模块,再让今日页承担记录入口和当天摘要。
把空白状态也当作正式界面
新用户的健康空间不预置示例记录。没有录入时显示“等待第一条记录”与明确的行动入口;未知营养数据保留为空值。这样既避免虚构用户状态,也使第一次操作的下一步足够清楚。
设计系统与规范Design system
健康记录的阅读顺序由任务决定:日期和当天摘要先于明细,记录动作靠近相关指标。组件以页面分区、卡片、字段、进度与空白状态复用,避免每类数据形成一套不同的操作语言。
没有数据时,给出下一步操作。
上图为原项目组件关系的组件说明。38% 为排版示意,不是任何用户的健康数据。
主动作保持靠近数据
饮食卡片连接“记录一餐”,饮水组件提供固定容量快捷操作,运动状态独立显示开始、暂停与结束。表单通过标签和单位降低歧义,未知值与零值使用不同表达。
原应用提供主题切换,并使用系统字体与语义控件;这份案例以白色透明表面展示结构,不宣称已经获得 Apple HIG 或无障碍认证。
核心交互与状态Key interactions
与财富 Pro 的 Canvas 扇区不同,WHIP 的饮水圆盘使用 SVG。这个组件只需要表达一个记录值与目标值的比例,SVG 能用更少的状态保持图形与可访问文本一致。
从比例到弧长
设记录饮水量为 a,目标为 t,比例 p = a / t。圆周长为 2πr;采用 pathLength="100" 后,可以直接把弧长写成百分比。绘制值封顶 100%,文字仍可保留实际比例。
这是圆盘计算的独立演示,不写入健康应用。
把“保存成功”放在反馈之前
记录数据先进入 repository,再写入 IndexedDB。界面通过 useLiveQuery 订阅变化,使今日摘要与记录列表从同一份保存结果更新。启动时若本地数据库不可访问,应用显示重试信息,不把失败包装成成功。
中断后的状态要能够解释
初始化会把仍标记为 active 的运动记录转换为 paused,并保留可用的更新时间。这样,重新打开后不会把关闭页面期间的时间悄悄算成持续运动。
架构决策与权衡Architecture
记录属于用户自己的设备,因此项目把 Dexie / IndexedDB 作为主要存储。四张表分别容纳 entries、foods、preferences 与 templates;日期与记录类型的索引承接回看与查询。
useLiveQuery 订阅保存结果
记录、食物、偏好、模板
缓存页面与必要静态资源
校验 → 事务写入 → 按 ID 去重
先解决断网记录,再界定同步边界
离线写入直接发生在本地数据库,不需要排队上传。Service Worker 负责应用壳缓存;它解决“页面能否打开”,不负责多端数据冲突。当前项目没有自动跨设备同步。更换设备需要导出与恢复,不能把这条路径描述为“断网重连后自动同步”。
| 选择 | 解决的任务 | 权衡与边界 |
|---|---|---|
| IndexedDB | 结构化记录、索引与事务 | 数据跟随浏览器来源,需考虑容量、清理与备份 |
| JSON 恢复 | 记录迁移与误操作后的恢复路径 | 合并按 ID 跳过已存在记录,不等于双向冲突合并 |
| 应用壳缓存 | 缓存就绪后离线打开核心页面 | 首次访问仍需联网;天气与可选模型有独立网络依赖 |
恢复是一组原子操作
导入先校验数据结构,再用跨表读写事务进行替换或合并。合并时通过 bulkGet 查重,只写入不存在的 ID;替换由界面要求明确确认。非法导入不会作为部分成功写入数据库。
本地优先减少了默认上传健康记录的需求,但不等同于端到端加密。设备丢失、站点数据清理与浏览器存储策略仍是需要面对的风险,因此备份入口属于核心能力。
交付成果与验证Impact
交付物包括五个主要模块、结构化本地记录、JSON 备份与恢复,以及 PWA Manifest 和 Service Worker 配置。下面区分项目原有的验证记录与本轮能够直接确认的实现。
页面、存储与安装配置
React / TypeScript 页面,Dexie 四张表,数据恢复事务;Manifest 设置 standalone,缓存使用更新提示,覆盖必要静态资源。
58 项自动测试与多尺寸渲染
项目 TEST_RESULTS.md 的 2026-10-23 记录记载 58/58 测试通过,并记录 380、1280、1440、1920 像素宽度的浏览器渲染。此处引用已有证据,本轮未重新执行应用测试。
缓存后的离线保存与重新打开
2026-10-22 记录记载停服后重新打开、保存 250 ml 饮水并浏览五个页面。该记录支持离线使用路径,不能推导所有网络功能都能离线。
真机安装与长期使用指标
iPhone Safari 安装生命周期、存储回收、首次安装完成率与长期留存没有本轮实测结果;因此不展示“安装率”“秒开率”等未经测量的指标。
下一轮验证应围绕实际任务
优先验证三条路径:首次记录是否能独立完成;已有记录能否在断网与重启后保留;更换设备时,备份文件是否能完整恢复。每条路径记录测试环境和失败条件,再形成可比较的基线。
查看实现依据与历史验证记录
- src/lib/db.ts:表结构、initialize、repository.import 与跨表事务。
- src/components/WaterDisc.tsx:比例计算、SVG 弧线与 progressbar 语义。
- src/main.tsx:启动状态、本地存储错误与重试入口。
- vite.config.ts:Manifest、Workbox 缓存与可选资源排除。
- 查看原项目验证记录(含日期与未验证范围)。
- 体验在线应用 · 查看在线应用。