docs: 文档/配置/测试同步 NAS :8124 生产现状,清除 Node.js 与甲骨文残留

背景:文档停在 Node.js 时代或甲骨文 8123 部署,与生产(NAS :8124 + Flask +
auth-hub + ai-gateway)严重脱节,曾导致凭旧记忆误判'无线上环境'。

- CLAUDE.md 重写:技术栈/结构/命令/部署事实/关键坑(F7 button、UTC 日期、
  429 退避以 DB 为准、迁移幂等、AI 生成耗时)
- docs/ARCHITECTURE.md 重写为 Flask 蓝图+services+可插拔数据层 + NAS 部署
- docs/DEVELOPMENT.md 重写为 Flask/CRA 开发指南 + push.sh 部署流程
- docs/REQUIREMENTS.md:部署条目改 NAS 8124;补 auth-hub/AI 教练/新修复
- docs/AUTH_HUB_INTEGRATION.md 新增(补 .env.example 悬空引用)
- README.md:技术栈/DB/auth-hub/API 清单/部署节修正
- backend/config.py 与 .env.example:AUTH_HUB_REDIRECT_URI 默认 8123→8124,
  MariaDB 注释 Oracle→NAS
- tests:GatewayCourtesy 并发测试对齐 MAX_CONCURRENT(AI_JOB_CONCURRENCY=2);
  conftest 禁用 create_app 后台队列线程,修整库测试 flaky(585 passed)
This commit is contained in:
ericwyuan
2026-09-02 19:34:32 +08:00
parent 68363957ec
commit 2d9a2be185
12 changed files with 609 additions and 496 deletions

192
CLAUDE.md
View File

@@ -1,88 +1,138 @@
# Garmin Health Lab - 项目指南
# Garmin Health Lab 项目指南
## 项目简介
佳明Garmin健康数据分析平台同步 Garmin Connect 数据,做多维度健康分析、
可视化与 AI 解读(晨报 / 趋势归因 / Copilot
Garmin Health Lab 是一个完整的健康数据分析平台,用于:
- 获取和同步佳明Garmin设备数据
- 进行多维度的健康数据分析
- 提供个性化的健康建议
- 可视化健康趋势
> **阅读顺序**:先读本文件(协作约定与现状速览)→ [PROGRESS.md](PROGRESS.md)
> (功能与部署进度,**排查前必读**)→ [README.md](README.md)API 与使用)→
> [docs/](docs/)(架构 / 开发 / 需求)。判断"部署在哪里、跑没跑、什么版本"时
> 一律以 `PROGRESS.md` 和 `deploy/` 脚本为准,**不要凭记忆断言**。
## 技术栈
## 技术栈现状2026-09
- **端**: React 18 + TypeScript + Recharts
- **后端**: Node.js + Express + TypeScript
- **数据库**: SQLite3
- **API 集成**: Garmin Connect API
- **端**Python 3.10+ / Flask应用工厂Gunicorn 生产运行。原 Node/Express
后端早已重写为 Python仓库中**不存在 `server/` 目录**。
- **前端**React 18 + TypeScript用 **CRAreact-scripts**构建UI 组件库为
**Framework7 9**`framework7-react`iOS 主题)+ Recharts 图表。根目录
`package.json` 是 npm workspaces`client`)。
- **数据库**:可插拔数据层(`backend/db.py``DB_TYPE` 切换——
本地开发 SQLite`backend/data/health.db`,默认);生产 NAS MariaDB
`garmin_health_lab` 库,连接配置见 NAS 上 `backend/.env`)。
- **认证****auth-hub SSO**OAuth2/OIDC`services/auth_hub_client.py`
本地邮箱密码注册/登录已移除;应用内 JWT 由后端签发。
- **AI**:自建 ai-gatewayOpenAI 兼容,`https://ai.zichuan.xyz/v1`)为唯一上游
NVIDIA 推理模型,单次生成可达 2~5 分钟);生产 `AI_MODEL_CHAIN=gateway`
## 快速开始
## 目录结构
### 安装
```bash
npm install
```
### 配置
```bash
cp server/.env.example server/.env
# 编辑 server/.env 填入 Garmin 凭证
GarminHealthLab/
├── backend/ # Flask 后端(当前唯一后端)
│ ├── app.py # 应用工厂:装配蓝图 + 静态 UI + scheduler/jobs
│ ├── wsgi.py # Gunicorn 入口
│ ├── config.py # 集中配置(读 backend/.env
│ ├── auth.py # JWT 签发/校验 + require_auth
│ ├── db.py # 可插拔数据层SQLite ↔ MariaDB+ 幂等迁移
│ ├── routes/ # API 蓝图blueprint
│ │ ├── auth.py # /api/auth auth-hub SSO: callback / logout / refresh / auth-hub/start
│ │ ├── garmin.py # /api/garmin 绑定/同步/MFA/退出/活动详情/同步详情
│ │ ├── health.py # /api/health 摘要/睡眠/心率/运动/身体成分/血氧/设备/挑战等
│ │ ├── analysis.py # /api/analysis 趋势/建议/briefing/trend-insight/copilot/insight
│ │ └── settings.py # /api/settings 个人资料/单位/同步频率/评分依据
│ ├── services/ # 业务逻辑(纯函数/无 Flask 依赖,可单测)
│ │ ├── garmin.py # Garmin API 同步核心(限流退避 24h 写 DB
│ │ ├── garmin_auth.py # Garmin OAuth 登录 + MFA 会话
│ │ ├── garmin_extras.py # 身体成分/血压/血氧/设备/徽章等扩展数据
│ │ ├── scheduler.py # 后台自动同步DB 锁,多 worker 只跑一次)
│ │ ├── ai.py / coach.py / insights.py / jobs.py # AI 教练 + 生产者/消费者队列
│ │ ├── analysis.py / health.py / fitness_age.py / settings.py
│ │ └── auth_hub_client.py / scopes.py
│ ├── data/ # SQLite本地开发git 忽略)
│ ├── static/ # 前端构建产物(生产由 Flask 同端口提供)
│ ├── tests/ # pytest 测试446+ 项)
│ └── .env.example # 环境变量样例(真实 .env 不提交)
├── client/ # React 前端CRA + Framework7
│ ├── src/pages/ # 今日/健康/趋势/运动/设置/每日/睡眠/指标详情等页面
│ ├── src/components/ # AI 晨报 / Copilot 浮窗 / 趋势归因 / Screen 骨架
│ ├── src/lib/ # day.ts本地日期/ metrics.ts指标注册表
│ ├── src/features.ts # 功能开关FEATURES.ai
│ └── .env.production # REACT_APP_API_URL=/api同源防 Network Error
├── deploy/ # NAS 部署脚本族S99garmin/start/stop/push/deploy
├── docs/ # 架构 / 开发 / 需求文档
├── PROGRESS.md # 进度与部署事实(排查必读)
└── README.md # 项目说明 + API 文档
```
### 开发
```bash
npm run dev
```
- 前端: http://localhost:3000
- 后端: http://localhost:5000
## 项目结构
- `client/` - React 前端应用
- `server/` - Node.js 后端服务
- `docs/` - 文档
详见 [ARCHITECTURE.md](docs/ARCHITECTURE.md) 和 [DEVELOPMENT.md](docs/DEVELOPMENT.md)
## 核心功能
1. **仪表板** - 健康数据概览和最近数据展示
2. **数据同步** - 从 Garmin 同步最新健康数据
3. **数据分析** - 趋势分析和数据可视化
4. **健康建议** - 基于数据的个性化建议
5. **设置** - 用户配置和偏好设置
## 关键特性
- ✅ Garmin API 集成
- ✅ 多维度数据分析(步数、心率、睡眠等)
- ✅ 实时数据同步
- ✅ 交互式数据可视化
- ✅ JWT 认证安全
- ✅ 本地数据存储
## 开发指南
- 详见 [DEVELOPMENT.md](docs/DEVELOPMENT.md)
- API 文档见 README.md
## 常用命令
```bash
npm run dev # 开发模式
npm run build # 构建项目
npm run typecheck # 类型检查
npm start # 生产模式
# 后端依赖(首次):在 backend/ 下建 .venv 并装 requirements-dev.txt
npm run setup:backend
# 同时起前后端开发backend:5000 由 BACKEND_PORT 固定client CRA 代理到 5000
npm run dev
# 单独起后端 / 前端 / 测试 / 类型检查 / 构建
npm run dev:backend
npm run dev:client
npm run test # backend/.venv/bin/python -m pytest446+ 项)
npm run typecheck
npm run build # client/react-scripts build → client/build/
# 冒烟测试(后端单测入口)
cd backend && .venv/bin/python tests/smoke.py
```
## 下一步任务
## 部署(生产 = NAS端口 8124
- [ ] 实现 Garmin OAuth 认证
- [ ] 完成 Garmin API 数据获取
- [ ] 实现仪表板可视化
- [ ] 添加数据分析算法
- [ ] 部署和优化
- **位置**NAS `192.168.50.64` `/volume1/web/garmin-health-lab`root 用户跑
gunicorn `0.0.0.0:8124`2 workers / 4 threads / --timeout 300开机自启走
DSM 任务调度器执行 `deploy/S99garmin.sh`
- **一键部署**:本地 `./deploy/push.sh`tar 经 ssh 同步 backend + deploy +
清空重推 client/build + sudo 重启,**校验 gunicorn pid 变化 + health 200**)。
前置:先 `npm run build`
- **公网**NAS frpc → 甲骨文 `http://129.146.26.249:8124`frp 重连需几秒)。
- **DB**NAS MariaDB 10.11root 经 socket `/run/mysqld/mysqld10.sock`(或
TCP 127.0.0.1:3306`garmin_health_lab`。10.11 dump 含 `/*M!999999`
注释、旧客户端会报错,且须 `--default-character-set=utf8mb4` 防中文丢失。
- **auth-hub**client `996aLPw4T5gl-rYZ`;回调注册了 LAN
`http://192.168.50.64:8124/auth/callback` 与公网
`http://129.146.26.249:8124/auth/callback` 两个地址。
- **部署/排障前**:先读 `PROGRESS.md``deploy/` 脚本确认事实(曾经凭旧记忆
断言"无线上环境"而误判)。服务以 root 运行:重启用 sudo日志
`logs/error.log``logs/access.log` 是 root 所有。
## 联系方式
## 关键约定与坑(写代码/改样式前看)
项目维护: ericwyuan.g@gmail.com
1. **日期一律本地日历日期**,别用 `toISOString()`UTCUTC+8 每天前 8 小时
查的是昨天)。前端统一走 `client/src/lib/day.ts`
2. **阈值全部来自公开参考值AI 只解读不定阈值**(设计原则,勿破)。
3. **Framework7 全局 `button { width: 100% }`** 会把任何 `<button>` 拉满父容器
——自定义组件里的按钮要显式 `width: auto`Copilot 浮窗 ✕/发送按钮曾因此
错位,见 `Copilot.css` 注释。F7 `.navbar .left/.right` 的 frosted pill 也
需在 `f7theme.css` 覆盖。
4. **同步限流**Garmin 账号 429 退避 24h`rate_limited_until`**DB 为准**
(多 worker 内存不一致会卡死守卫);`_is_rate_limited` 沿异常 `__cause__`
链识别 RetryError 里的 429。
5. **AI 生成慢**:网关上游推理模型单次 2~5 分钟,晨报走后台生成 + 轮询,
接口超时/流式不可靠见 `services/ai.py` 的非流式回退;生产队列并发
`AI_JOB_CONCURRENCY=2`(共享网关,太高会把别家打成 502
6. **迁移幂等**`db.py``init_db()` 会被多 worker 并发调用,所有
`ALTER/CREATE` 必须幂等(`CREATE TABLE IF NOT EXISTS` + 先查列再加列)。
7. **不要提交**`.env`、构建产物 `client/build`、SQLite 数据、`.workbuddy/`
`.claude/`(已在 .gitignore。改代码后同步 `backend/static/` 用 deploy 流程。
8. **一任务一 commit**,完成即推送 NAS Giteaorigin 就是 Gitea
## 测试
- pytest446+ 项)覆盖:设置吸附/校验、身体年龄、运动详情列存解析、Garmin
同步入库与只读本地保证、AI 缓存/队列、调度器等。改后端先跑
`npm run test`(或 `cd backend && .venv/bin/python -m pytest`)。
- 前端无单测框架,用 Chrome headless + CDP 截图做界面回归(见每日日志)。
## 下一步 / 已知问题
-`PROGRESS.md` 的待办区与 `docs/REQUIREMENTS.md`
- 已知独立 bugNAS `logs/stdout.log` 里 `refill_backlog ... SQL syntax near
'TEXT)) AND NOT EXISTS'` 反复刷——某条 AI 回填 SQL 与 NAS MariaDB 语法对
不上,尚未修复。