feat: init fitness-coach (backend + miniprogram)

- backend: NestJS service with exercise/plan data
- miniprogram: WeChat mini program client
- exclude node_modules, dist, runtime data-store, local env
This commit is contained in:
2026-07-22 00:35:40 +08:00
commit b3b58e66fb
103 changed files with 154759 additions and 0 deletions

78
backend/README.md Normal file
View File

@@ -0,0 +1,78 @@
# FITCOACH 后端NestJS
健身动作数据代理与推荐服务。所有动作数据统一存储在后端,向前端小程序提供 REST 接口。
## 技术栈
- NestJS 10 + Express
- 内存数据集(构建时由 `exercises-dataset` 导入),查询/筛选/推荐均在内存完成,毫秒级响应
- 可选静态媒体服务(`/media`,指向 `backend/media/`
## 环境变量(`.env`,参考 `.env.example`
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `PORT` | `3000` | 服务端口 |
| `API_BASE_URL` | `http://localhost:3000` | 小程序访问基址(生成媒体 URL 用) |
| `MEDIA_BASE_URL` | `http://localhost:3000/media` | 媒体资源基址;可改为 CDN |
| `CORS_ENABLED` | `true` | 是否允许跨域Web 调试用) |
## 安装与运行
```bash
npm install
npm run build # 触发 prebuild: 自动下载 exercises.json 到 src/exercises/data/
npm run start:dev # 开发watch
npm run start:prod # 生产node dist/main.js
```
## 脚本
- `npm run sync:media` — 将数据集的图片/动画同步到 `backend/media/`(供 `/media` 提供)。可选环境变量 `MEDIA_CONCURRENCY`(并发)、`MEDIA_ONLY=gif|image`
- `node scripts/analyze.mjs` — 扫描数据集,输出各维度去重值与缺失的中文标签(用于补全 `labels.ts`)。
## 数据导入说明
数据集 `exercises.json`1,324 条)通过 `scripts/ensure-data.mjs` 在构建时自动从 GitHub 下载;
也可手动把 `exercises-dataset/data/exercises.json` 复制到 `src/exercises/data/exercises.json`
服务启动时由 `ExercisesService.onModuleInit()` 读取并 `normalize()` 为带中文字段的结构化对象。
## 接口示例
```bash
# 列表 + 筛选(按器械 dumbbell分页
curl "http://localhost:3000/api/exercises?equipment=dumbbell&pageSize=5"
# 动作详情
curl "http://localhost:3000/api/exercises/0001"
# 目标肌群智能推荐(肱二头肌,限定哑铃)
curl "http://localhost:3000/api/recommend?target=biceps&equipment=dumbbell&limit=10"
# 分类元数据
curl "http://localhost:3000/api/categories/targets"
curl "http://localhost:3000/api/categories/equipment"
# 训练组合
curl "http://localhost:3000/api/collections"
curl "http://localhost:3000/api/collections/legs/exercises?pageSize=10"
# 搜索
curl "http://localhost:3000/api/search?q=abs"
```
## 推荐算法
对每条动作计算相关性评分:
- 目标肌群完全匹配 `target`+100理由「主要训练 XX」
- 出现在协同肌群 `secondaryMuscles`+40理由「协同训练 XX」
- 指定器械匹配:+30若为自重可替代+10
仅返回评分 > 0 的动作,按评分降序、名称升序返回。
## 目录
```
src/exercises/
├── exercises.module.ts
├── exercises.service.ts # 数据加载、筛选、分类、推荐、组合
├── exercises.controller.ts # /api 路由
├── exercises.interface.ts # 类型定义
├── dto/ # QueryExercisesDto / RecommendQueryDtoclass-validator 校验)
├── utils/normalize.ts # 原始 → 结构化(类型推导、媒体 URL、中文标签
└── data/
├── exercises.json # 数据集(构建时生成)
├── labels.ts # 中英文标签映射
└── collections.ts # 智能训练组合定义
```