Commit Graph

3 Commits

Author SHA1 Message Date
ericwyuan
7ab150537d [阶段10] 前端以 Framework7 重建,采用 iOS 原生形态
按要求废弃手写外壳,改用 Framework7 React(theme=ios)。参照 PeakWatch
的信息架构与卡片语言。

保留(这些是资产,不该重来):
- 数据层 services/api.ts、聚合 lib/aggregate.ts、参考区间 lib/ranges.ts
- 图表组件 Chart / Ring / Sparkline / BandBar / MetricCard / MetricStrip
- 经校验的配色令牌(色盲安全 + 对比度,浅深两档)

替换:
- 路由与外壳交给 F7:五个 Tab 各自独立导航栈,推入详情页不影响其他 Tab
- 页面转场、橡皮筋滚动、大标题折叠、半透明栏 —— 这些正是换框架的理由,
  手写做不像
- 底部标签栏改用 F7 Toolbar,触控目标与安全区由框架处理

配色接入:
- 新增 f7theme.css 把我们的令牌映射到 F7 的 CSS 变量,让它的导航栏/
  列表/面板与我们的图表同属一套设计,而不是两种视觉打架
- F7 的深色靠 .dark 类,我们的靠 data-theme,两者在 App 里同步切换

fix: 图标显示为原始名称(squ/hea/cale…)
- iconIos/iconMd 引用的是 framework7-icons 字体,没装就只会渲染出名字

其他:
- tsconfig moduleResolution 改为 bundler —— F7 用 exports 映射,
  node 解析方式找不到它的类型
- 登录页不套 Tab 外壳,未登录时不该出现导航

桌面与手机都要好看:内容在宽屏收进 1100px 居中列并加密卡片列数,
窄屏走底部标签栏;两档都已实机核对。

bundle 190KB -> 399KB,是换取原生手感的代价。

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-23 23:38:21 +08:00
ericwyuan
757afdc941 [阶段9] 界面打磨:hero 圆环、sparkline、骨架屏、动效
参考了 itsdrchen/Garmin-AI-Coach 与主流健康 App(Apple 活动圆环、
Oura/Whoop 的评分环、Garmin Connect 的卡内趋势)的做法。

hero 区(每个视图只有一个 hero 数字):
- 步数目标圆环,超额时转为 status-good 色并保持满环 + 端点标记,
  而不是绕第二圈 —— 绕圈会让 101% 看起来比 100% 还少
- 圆环轨道用填充色同色系的浅阶而非中性灰,两者才读作同一个量器

sparkline(12 点,卡片内嵌):
- 线用去强调色,只有最新一点用强调色,让它成为数字的背景而非对手
- null 处断开而不插值 —— 设备没记录的那天连一条平线过去等于编数据

骨架屏取代转圈:
- 形状与将要出现的内容一致,数据到位时布局不跳
- 用扫光而非闪烁,读起来像进度而不是元素在求关注

动效:
- 卡片/图表依次入场(45ms 递增),引导视线扫过而不是整屏同时砸下来
- 数字滚动到位、圆环扫过、sparkline 描线、悬停抬升、按下微缩
- 全部尊重 prefers-reduced-motion:直接跳过而非缩短时长 ——
  引起不适的是位移本身,不是它持续多久

深色改为冷调(借鉴参考项目):
- 表面从暖近黑 #1a1a19 改为冷近黑 #181b21,更像运动 App
- 换表面意味着原有校验作废,已用校验器对新表面重跑:四个系列色
  全部通过含 3:1 对比度;文字亦逐个复核(正文 14.56:1、
  次要 7.98、弱化 4.38、按钮白字 6.63)

fix(a11y): 大号独立数字不应使用 tabular-nums
- 等宽数字让每个字形都占 0 的宽度,大字号下显得松散;
  等宽只保留给需要纵向对齐的表格列与坐标轴刻度

fix: 数字滚动动画吞掉了小数位
- StatTile 内部按 decimals 格式化,而调用方已经先 round 过一次,
  距离显示成 "9 km"、久坐成 "11 小时"。改为传原值 + decimals

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-23 22:48:09 +08:00
ericwyuan
bfda1cd017 [阶段8] 新增每日数据模块;趋势改为全指标并列 + 周期聚合
每日数据(新页面 /daily):
- 按活动/能量/心率/压力/睡眠/血氧呼吸/训练七组,列出全部 40 项指标
- 日期选择器 + 前后一天翻页;"只显示有数据的指标"开关
- 附当天的运动记录明细
- 标题处显示当天记录到多少项,缺数据一目了然

趋势(重写):
- 15 组指标全部并列展示,不再一次只能看一个
- 标签可逐个隐藏/显示,选择存入 localStorage(每次刷新都重置的
  选择算不上偏好);提供全选/全不选
- 两级筛选:范围(一月/一季/半年/一年/两年)× 周期(每天/每 7 天/
  每月/每季度)。周期选项按范围过滤,避免出现"近一月按季度聚合"
- 所有图表共用同一份聚合结果,一行筛选器统摄全部图表

聚合口径(lib/aggregate.ts):
- 无论累计型还是速率型指标,一律折算为"周期内日均",这样 30 天的
  月份和 31 天的月份不会仅因日历差 3%
- 周按最新一天往回切,而不是按自然周一 —— 否则开头会出现一个半空
  的桶,看起来像低谷,其实只是窗口起点
- 累计型指标的统计标签写作"日均"而非"平均",读者不必猜口径

fix(viz): 聚合后柱形/面积图掩盖了变化
- 柱形与面积都以延展量编码大小,必须从 0 起;而一年的月均步数都在
  9,590~12,701 之间,画出来几乎一样高,恰恰看不见要看的变化
- 聚合视图改用折线:折线编码位置而非延展量,非零轴是正当的。
  改后 y 轴自动落在 9350~12750,走势清晰可读

fix(health): 运动记录按日期筛选时 500
- get_activities 复用了按 date 列过滤的子句,但 activities 表只有
  start_time,报 "Unknown column 'date'"。此前唯一的调用方不传
  日期,所以一直没暴露,每日数据页一传就炸
- 上界改用次日零点的开区间:SQLite 按字符串比较,而存储的分隔符
  可能是 'T'(0x54) 也可能是空格(0x20),写成 "end 23:59:59" 会让
  当天 18:30 的记录排在上界之后而被排除在自己那天之外

tests (+6, 共 305): 运动记录的单日范围、上下界闭合、仅起点/仅终点、
不传范围返回全部、端点级验证

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-23 22:33:59 +08:00