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:
89
README.md
89
README.md
@@ -13,20 +13,21 @@
|
||||
## 🛠 技术栈
|
||||
|
||||
### 前端
|
||||
- React 18 + TypeScript
|
||||
- React 18 + TypeScript(CRA / 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 统一 SSO(OAuth2/OIDC,本地密码登录已移除)
|
||||
- garminconnect(Garmin 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(生产)**:运行于 NAS(192.168.50.64)本地 MariaDB 10.11,root 经
|
||||
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):
|
||||
前端(React,CRA 开发服务器,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)
|
||||
|
||||
## 📄 许可证
|
||||
|
||||
|
||||
Reference in New Issue
Block a user