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

View File

@@ -13,20 +13,21 @@
## 🛠 技术栈
### 前端
- React 18 + TypeScript
- React 18 + TypeScriptCRA / react-scripts 构建)
- Framework7 9`framework7-react`iOS 风格 UI
- Recharts (数据可视化)
- Tailwind CSS (样式)
- Axios (API 请求)
- Axios (API 请求JWT 拦截器)
### 后端
- Python 3.10+ + Flask
- Gunicorn生产运行
- 可插拔数据层SQLite本地开发/ MariaDB生产Oracle 云服务器本地 MariaDB 10.3,经 PyMySQL
- JWT 鉴权 + scrypt 密码哈希
- garminconnect可选Garmin API 集成
- Python 3.10+ + Flask(应用工厂)
- Gunicorn生产运行NAS :8124
- 可插拔数据层SQLite本地开发/ MariaDB生产NAS 10.11 库
`garmin_health_lab`,经 PyMySQL/socket
- JWT 鉴权;登录走 auth-hub 统一 SSOOAuth2/OIDC本地密码登录已移除
- garminconnectGarmin API 集成)
> 注:原 Node/TypeScript 后端保留在 `server/`(仅 service 逻辑骨架);
> 当前可运行实现为 `backend/` 下的 Python/Flask 单体服务
> 早期 Node.js/TypeScript 后端`server/`)已整体重写为 `backend/` 下的
> Python/Flask 单体,目录已删除
## 📁 项目结构
@@ -39,13 +40,13 @@ GarminHealthLab/
│ ├── wsgi.py # Gunicorn 入口
│ ├── config.py # 配置(读 .env
│ ├── db.py # 可插拔数据层 (SQLite / MariaDB)
│ ├── auth.py # scrypt + JWT + require_auth
│ ├── auth.py # JWT 签发/校验 + require_auth
│ ├── services/ # 业务逻辑 (health / analysis / garmin)
│ ├── routes/ # 蓝图 (auth / garmin / health / analysis)
│ ├── tests/smoke.py # 冒烟测试
│ ├── requirements.txt
│ └── .env.example
├── server/ # 原 Node/TS 后端(仅 service 骨架,未接入路由)
├── server/ # (已删除)原 Node/TS 后端,已重写为 backend/
├── docs/ # 文档
├── package.json # 工作空间根配置
└── README.md
@@ -85,22 +86,23 @@ JWT_SECRET=your_jwt_secret_here # 生产务必更换
CORS_ORIGIN=http://localhost:3000,http://localhost:5173
```
> 原 `server/.env` 的 Node 配置已弃用,请改用 `backend/.env`。
> 早期 Node 后端的配置方式已弃用,一律使用 `backend/.env`。
### 数据库SQLite / MariaDB 可插拔
数据层通过 `DB_TYPE` 环境变量切换后端,**业务代码无需改动**
- **SQLite默认本地开发**:零配置,由 `DATABASE_PATH` 指定文件位置。
- **MariaDB生产**:运行于 Oracle 云服务器129.146.26.249)本地 MariaDB 10.3专用账号 `garmin``127.0.0.1:3306` 连接PyMySQL
生产使用独立库 `garmin_health_lab`(与 `sentinel_home_ai` 隔离)。完整配置见 `backend/.env.example`
- **MariaDB生产**:运行于 NAS192.168.50.64)本地 MariaDB 10.11root 经
socket `/run/mysqld/mysqld10.sock`(或 TCP `127.0.0.1:3306`连接PyMySQL
独立库 `garmin_health_lab`。完整配置见 `backend/.env.example`
```env
DB_TYPE=mariadb
MARIADB_SOCKET=/run/mysqld/mysqld10.sock
MARIADB_HOST=127.0.0.1
MARIADB_PORT=3306
MARIADB_USER=garmin
MARIADB_USER=root
MARIADB_PASSWORD=your_production_mariadb_password
MARIADB_DATABASE=garmin_health_lab
```
@@ -117,14 +119,18 @@ python app.py
# 或生产方式gunicorn wsgi:app -b 0.0.0.0:5000
```
前端(Vite/React端口 3000 或 5173
前端ReactCRA 开发服务器proxy 到后端 5000
```bash
npm run dev
npm install # 在仓库根目录执行workspaces 装 client
npm run dev # 同时起后端 5000 + 前端 3000或分别 dev:backend / dev:client
```
- 前端: http://localhost:3000
- 后端 API: http://localhost:5000/api
> 登录走 auth-hub SSO点登录会跳到统一认证页回跳后后端签 JWT。
> 数据库首次启动自动建表(`db.init_db()`,幂等)。
### 冒烟测试
```bash
@@ -134,15 +140,25 @@ python tests/smoke.py
## 📚 API 文档
### 认证
- `POST /api/auth/register` - 用户注册email, garminEmail, garminPassword
- `POST /api/auth/login` - 用户登录email, password
- `POST /api/auth/logout` - 用户登出
### 认证auth-hub 统一 SSO
- `POST /api/auth/auth-hub/start` - 发起 SSO 登录(返回 auth-hub 授权 URL
- `GET /api/auth/callback?code=…` - auth-hub 回调(浏览器跳转,签发 JWT
- `POST /api/auth/refresh` - 刷新 Token
- `POST /api/auth/logout` - 登出
> 本地邮箱/密码注册登录已移除;账号体系由 auth-hub 统一提供
> (见 [AUTH_HUB_INTEGRATION.md](docs/AUTH_HUB_INTEGRATION.md))。
> Garmin 账号的绑定/解绑走 `/api/garmin/*`(见下),与 Web 登录相互独立。
### Garmin 数据同步
- `POST /api/garmin/login` - 发起 Garmin OAuth 授权(需验证码时 `POST /api/garmin/mfa` 提交)
- `GET /api/garmin/auth-status` / `GET /api/garmin/login-status` - 授权状态
- `DELETE /api/garmin/login` / `POST /api/garmin/disconnect` - 退出/解绑 Garmin 账号
- `POST /api/garmin/sync` - 同步 Garmin 数据
- `GET /api/garmin/status` - 获取同步状态
- `POST /api/garmin/sync-latest` - 仅同步最新数据
- `POST /api/garmin/sync-details` - 补齐运动详情/全天曲线(后台队列)
- `GET /api/garmin/status` / `GET /api/garmin/auto-sync` - 同步状态
- `GET /api/garmin/activities/<activity_id>/detail` - 单次运动详情
### 健康数据
- `GET /api/health/summary` - 获取健康摘要
@@ -150,6 +166,10 @@ python tests/smoke.py
- `GET /api/health/heart-rate` - 获取心率数据
- `GET /api/health/sleep` - 获取睡眠数据
- `GET /api/health/activities` - 获取运动数据
- `GET /api/health/fitness-age` - 身体年龄
- `GET /api/health/series` - 全天曲线(心率/压力/身体电量/呼吸/血氧)
- `GET /api/health/body-composition` / `blood-pressure` / `race-predictions`
- `GET /api/health/badges` / `personal-records` / `challenges` / `devices`
### 分析与建议
- `GET /api/analysis/trends` - 获取数据趋势
@@ -169,20 +189,31 @@ python tests/smoke.py
- 请求体 `{question, history?, date?, model?}`
- 事件序列 `start``delta`* → `done`,失败时为 `error`
> AI 相关接口全部经由自建 **ai-gateway**OpenAI 兼容,见 `AI_GATEWAY_BASE_URL`)。
> AI 相关接口全部经由自建 **ai-gateway**OpenAI 兼容,`https://ai.zichuan.xyz/v1`
> 见 `AI_GATEWAY_BASE_URL`)。
> 该网关的主上游是大型推理模型,一次生成实测需 2~5 分钟,因此简报走后台生成 +
> 轮询,趋势归因与 Copilot 走显式触发;任一模型失败时降级为规则引擎,
> `meta.source` 会说明本次由谁作答。
## 🚀 部署(生产 = NAS
- **位置**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`
- **公网**NAS frpc → `http://129.146.26.249:8124`
- **一键部署**:先 `npm run build`,再 `./deploy/push.sh`(同步 backend +
deploy + 清空重推 `client/build` + sudo 重启 + pid/health 双校验)。
- **部署排障前**:先读 `PROGRESS.md``deploy/` 脚本确认事实。
## 🔐 安全说明
- Garmin 账户密码使用加密存储
- 所有 API 请求需要 JWT 认证
- 敏感数据不在前端存储
- Garmin 账户密码不入库(令牌授权,约一年有效)
- 所有 API 请求需要 JWT 认证auth-hub SSO 签发)
- 敏感数据不在前端存储`backend/.env` 含密钥,不提交 git
## 📝 开发指南
详见 [DEVELOPMENT.md](./docs/DEVELOPMENT.md)
详见 [DEVELOPMENT.md](./docs/DEVELOPMENT.md) 与 [ARCHITECTURE.md](./docs/ARCHITECTURE.md)
## 📄 许可证