From b5b2eba6f8aa7abe8bc5f95246f7450e909cd94e Mon Sep 17 00:00:00 2001 From: Rocky Date: Sat, 17 Jan 2026 22:11:13 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=20Vitals=20=E5=81=A5?= =?UTF-8?q?=E5=BA=B7=E7=AE=A1=E7=90=86=E5=BA=94=E7=94=A8=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 综合健康管理:运动、饮食、睡眠、体重 - CLI + Web 仪表盘双交互模式 - 支持佳明/咕咚数据导入 - 智能卡路里计算,支持拍照识别食物 - 周报/月报多格式导出(HTML/PDF/PNG) Co-Authored-By: Claude Opus 4.5 --- docs/plans/2025-01-17-vitals-design.md | 368 +++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 docs/plans/2025-01-17-vitals-design.md diff --git a/docs/plans/2025-01-17-vitals-design.md b/docs/plans/2025-01-17-vitals-design.md new file mode 100644 index 0000000..05793b1 --- /dev/null +++ b/docs/plans/2025-01-17-vitals-design.md @@ -0,0 +1,368 @@ +# Vitals 健康管理应用设计文档 + +> 生成日期: 2025-01-17 + +## 概述 + +Vitals 是一个本地优先的综合健康管理应用,整合运动、饮食、睡眠和体重数据,提供统一的仪表盘和定期报告。 + +**核心特点:** +- 数据本地存储,隐私有保障 +- 支持从佳明手表、咕咚APP导入数据 +- 命令行快速记录 + Web 可视化仪表盘 +- 智能卡路里计算,支持拍照识别食物 +- 周报/月报自动生成 + +--- + +## 整体架构 + +``` +┌─────────────────────────────────────────────────────┐ +│ 用户交互层 │ +├──────────────────────┬──────────────────────────────┤ +│ CLI 命令行工具 │ Web 仪表盘 (本地) │ +│ - 快速记录数据 │ - 数据可视化 │ +│ - 导入外部数据 │ - 趋势图表 │ +│ - 生成报告 │ - 健康概览 │ +└──────────────────────┴──────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 核心服务层 │ +│ - 数据标准化处理 │ +│ - 报告生成引擎 │ +│ - 数据导入适配器 (Garmin / 咕咚 / CSV) │ +│ - 食物识别与卡路里计算 │ +└─────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────┐ +│ 数据存储层 │ +│ SQLite 本地数据库 │ +│ - 运动记录 - 饮食记录 - 睡眠记录 - 体重记录 │ +└─────────────────────────────────────────────────────┘ +``` + +**设计原则:** +- 本地优先:所有数据存储在本地 SQLite,不依赖云服务 +- 模块解耦:CLI、Web、数据处理各自独立 +- 可扩展:通过适配器模式支持新的数据源 + +--- + +## 数据模型 + +### 运动记录 (exercise) +| 字段 | 类型 | 说明 | +|-----|------|-----| +| id | INTEGER | 主键 | +| date | DATE | 日期 | +| type | TEXT | 运动类型(跑步/游泳/力量...) | +| duration | INTEGER | 时长(分钟) | +| calories | INTEGER | 消耗卡路里 | +| distance | FLOAT | 距离(公里,可选) | +| heart_rate_avg | INTEGER | 平均心率(可选) | +| source | TEXT | 数据来源(手动/garmin/codoon) | +| raw_data | JSON | 原始导入数据 | +| notes | TEXT | 备注 | + +### 饮食记录 (meal) +| 字段 | 类型 | 说明 | +|-----|------|-----| +| id | INTEGER | 主键 | +| date | DATE | 日期 | +| meal_type | TEXT | 餐次(早/中/晚/加餐) | +| description | TEXT | 食物描述 | +| calories | INTEGER | 总卡路里 | +| protein | FLOAT | 蛋白质(克,可选) | +| carbs | FLOAT | 碳水(克,可选) | +| fat | FLOAT | 脂肪(克,可选) | +| photo_path | TEXT | 照片路径(可选) | +| food_items | JSON | 解析后的食物条目 | + +### 睡眠记录 (sleep) +| 字段 | 类型 | 说明 | +|-----|------|-----| +| id | INTEGER | 主键 | +| date | DATE | 日期 | +| bedtime | TIME | 入睡时间 | +| wake_time | TIME | 起床时间 | +| duration | FLOAT | 总时长(小时) | +| quality | INTEGER | 质量评分(1-5) | +| deep_sleep_mins | INTEGER | 深睡时长(可选) | +| source | TEXT | 数据来源 | +| notes | TEXT | 备注 | + +### 体重记录 (weight) +| 字段 | 类型 | 说明 | +|-----|------|-----| +| id | INTEGER | 主键 | +| date | DATE | 日期 | +| weight_kg | FLOAT | 体重(公斤) | +| body_fat_pct | FLOAT | 体脂率(可选) | +| muscle_mass | FLOAT | 肌肉量(可选) | +| notes | TEXT | 备注 | + +### 用户配置 (config) +| 字段 | 类型 | 说明 | +|-----|------|-----| +| age | INTEGER | 年龄 | +| gender | TEXT | 性别 | +| height | FLOAT | 身高(厘米) | +| weight | FLOAT | 当前体重 | +| activity_level | TEXT | 活动水平 | +| goal | TEXT | 目标(减重/维持/增肌) | +| bmr | INTEGER | 基础代谢(自动计算) | +| tdee | INTEGER | 日常总消耗(自动计算) | + +--- + +## CLI 命令设计 + +```bash +# ===== 数据记录 ===== +vitals log weight 72.5 # 记录体重 +vitals log weight 72.5 --fat 18.5 # 带体脂率 +vitals log meal 早餐 "燕麦+鸡蛋+牛奶" # 记录饮食 +vitals log meal 午餐 --photo ~/lunch.jpg # 拍照记录饮食 +vitals log sleep 23:30 07:00 --quality 4 # 记录睡眠 +vitals log exercise 跑步 30min --distance 5km # 手动记录运动 + +# ===== 数据导入 ===== +vitals import garmin ~/Downloads/export.zip # 导入佳明数据 +vitals import codoon ~/Downloads/codoon.json # 导入咕咚数据 +vitals import csv ~/data.csv --type weight # 通用CSV导入 + +# ===== 数据查看 ===== +vitals show today # 今日概览 +vitals show week # 本周汇总 +vitals show weight --days 30 # 最近30天体重趋势 + +# ===== 报告生成 ===== +vitals report week # 生成周报(终端输出) +vitals report week --output report.html # HTML导出 +vitals report week --output report.md # Markdown导出 +vitals report week --output report.pdf # PDF导出 +vitals report week --output report.png # 图片导出 +vitals report month # 生成月报 + +# ===== 个人配置 ===== +vitals config set --age 28 --gender male --height 175 --weight 72 +vitals config set --activity-level moderate +vitals config set --goal lose + +# ===== Web 仪表盘 ===== +vitals dashboard # 启动本地Web服务 +``` + +**设计说明:** +- 日期默认今天,可用 `--date 2024-01-15` 覆盖 +- 根据文件后缀自动选择导出格式 +- 图片导出宽度 1080px,适配手机分享 + +--- + +## 数据导入适配器 + +### Garmin 佳明 + +**导入方式:** +- 从 Garmin Connect 网站导出数据包 (ZIP格式) +- 或通过 Garmin Connect API(需授权) + +**支持数据:** +- 运动记录:跑步、骑行、游泳、力量训练等 +- 睡眠数据:入睡/起床时间、深睡/浅睡时长 +- 心率数据:静息心率、运动心率 +- 体重数据:如使用 Garmin 体重秤 + +**文件解析:** ZIP 包内含 FIT 文件和 JSON 摘要,优先解析 JSON + +### 咕咚 Codoon + +**导入方式:** 咕咚APP → 设置 → 数据导出 → 下载 JSON/GPX 文件 + +**支持数据:** +- 运动记录:跑步、健走、骑行 +- 运动轨迹:GPX 格式,可选保留 +- 运动统计:配速、心率、卡路里 + +### 去重策略 + +- 同一天 + 同一运动类型 + 时间差 <5分钟 → 视为重复 +- 保留规则:优先保留数据更完整的记录 +- 冲突提示:发现疑似重复时询问用户处理方式 + +--- + +## 卡路里管理 + +### 食物卡路里推算 + +**文字输入:** +```bash +vitals log meal 午餐 "一碗米饭+红烧肉+炒青菜" +# 系统自动解析: +# → 米饭(200g): 230卡 +# → 红烧肉(100g): 320卡 +# → 炒青菜(150g): 45卡 +# → 总计: 595卡 +``` + +**图片输入:** +```bash +vitals log meal 午餐 --photo ~/lunch.jpg +# 系统识别: +# → 检测到: 米饭、红烧排骨、西兰花 +# → 估算热量: 约 680 卡 +``` + +**技术实现:** +- 内置常见食物数据库(约 2000+ 种中国常见食物) +- 支持自然语言描述,智能拆分食物条目 +- 图片识别优先使用 Claude Vision API,备选本地模型 +- 用户修正后记入个人食物库,提升准确度 + +**图片存储:** +- 原图保存至 `~/.vitals/photos/YYYY/MM/DD-meal_type.jpg` +- 可选压缩存储节省空间 + +### 每日卡路里收支 + +``` +┌─────────────────────────────────────────────────┐ +│ 今日卡路里收支 │ +├─────────────────────────────────────────────────┤ +│ 基础代谢 (BMR) 1,650 卡 │ +│ + 日常活动消耗 330 卡 │ +│ + 运动消耗 420 卡 │ +│ ───────────────────────────────── │ +│ = 今日总消耗 2,400 卡 │ +│ │ +│ - 早餐 470 卡 │ +│ - 午餐 595 卡 │ +│ - 晚餐 680 卡 │ +│ ───────────────────────────────── │ +│ = 今日摄入 1,745 卡 │ +│ │ +│ 差值: -655 卡 (热量缺口,有助于减重) │ +└─────────────────────────────────────────────────┘ +``` + +--- + +## Web 仪表盘 + +**技术选型:** +- 后端:FastAPI +- 前端:HTML + Chart.js +- 运行:`vitals dashboard` 启动,访问 http://localhost:8080 + +**页面结构:** +- 首页:今日概览 + 卡路里收支 + 趋势图表 +- 运动页:运动历史列表 + 统计图表 +- 饮食页:饮食记录日历视图 + 图片回顾 +- 睡眠页:睡眠质量趋势 +- 体重页:体重变化曲线 + 目标线 +- 报告页:生成和下载周报/月报 + +--- + +## 报告生成 + +### 输出格式 + +| 格式 | 说明 | +|-----|------| +| 终端 | 彩色文本,直接查看 | +| HTML | 精美排版,浏览器打开 | +| Markdown | 方便存档 | +| PDF | 正式文档 | +| PNG | 适合分享到微信/朋友圈,宽度 1080px | + +### 周报内容 + +- 本周概览:运动次数、总时长、消耗卡路里 +- 睡眠统计:平均时长、质量评分 +- 体重变化:起止体重、变化量 +- 卡路里收支:平均每日摄入 vs 消耗 +- 运动详情:每日运动记录 +- 趋势洞察:与上周对比、进展评估 + +### 月报额外内容 + +- 月度目标完成情况 +- 与上月同期对比 +- 本月最佳/最差记录 +- 长期趋势分析 + +--- + +## 项目结构 + +``` +vitals/ +├── pyproject.toml # 项目配置 +├── README.md +│ +├── src/vitals/ +│ ├── __init__.py +│ ├── cli.py # CLI 入口 +│ │ +│ ├── core/ +│ │ ├── models.py # 数据模型 +│ │ ├── database.py # SQLite 操作 +│ │ ├── calories.py # 卡路里计算 +│ │ └── report.py # 报告生成 +│ │ +│ ├── importers/ +│ │ ├── base.py # 适配器基类 +│ │ ├── garmin.py # 佳明导入 +│ │ ├── codoon.py # 咕咚导入 +│ │ └── csv.py # CSV导入 +│ │ +│ ├── vision/ +│ │ ├── analyzer.py # 食物识别 +│ │ └── providers/ +│ │ ├── claude.py # Claude Vision +│ │ └── local.py # 本地模型 +│ │ +│ ├── web/ +│ │ ├── app.py # FastAPI +│ │ ├── static/ +│ │ └── templates/ +│ │ +│ └── data/ +│ └── food_database.json # 食物热量库 +│ +├── tests/ +└── docs/ +``` + +--- + +## 技术依赖 + +| 库 | 用途 | +|---|------| +| typer | CLI 框架 | +| sqlite3 | 数据库(内置) | +| fastapi | Web 框架 | +| uvicorn | ASGI 服务器 | +| chart.js | 前端图表 | +| weasyprint | PDF 导出 | +| playwright / html2image | 图片导出 | +| anthropic | Claude API(食物识别) | + +--- + +## 下一步 + +1. 初始化项目结构 +2. 实现核心数据模型和数据库 +3. 实现 CLI 基础命令 +4. 实现数据导入适配器 +5. 实现卡路里计算和食物识别 +6. 实现 Web 仪表盘 +7. 实现报告生成