feat(training-plans): 添加训练项目管理功能

- 新增训练项目模型、DTO和服务,支持创建、更新、删除和批量操作训练项目
- 在控制器中实现训练项目的相关API,包括添加、批量添加、获取、更新、删除和标记完成状态
- 提供训练项目的完成统计功能,支持获取训练计划下所有项目的完成情况
- 更新训练计划模块以集成训练项目管理功能
This commit is contained in:
richarjiang
2025-08-15 09:44:42 +08:00
parent 2c04325152
commit 8edc27b0ad
7 changed files with 1429 additions and 5 deletions

View File

@@ -0,0 +1,374 @@
# 训练计划项目管理 API 使用示例
## 创建一个完整的训练计划项目
### 1. 创建基础训练计划
```bash
POST /training-plans
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "全身力量训练",
"startDate": "2024-01-15T00:00:00.000Z",
"mode": "daysOfWeek",
"daysOfWeek": [1, 3, 5],
"sessionsPerWeek": 3,
"goal": "core_strength"
}
```
响应:
```json
{
"id": "plan_1705123456789_abc123",
"name": "全身力量训练",
"isActive": true,
"userId": "user_123",
"startDate": "2024-01-15T00:00:00.000Z",
"mode": "daysOfWeek",
"daysOfWeek": [1, 3, 5],
"sessionsPerWeek": 3,
"goal": "core_strength",
"createdAt": "2024-01-10T10:30:00.000Z"
}
```
### 2. 批量添加训练项目
```bash
POST /training-plans/plan_1705123456789_abc123/exercises/batch
Authorization: Bearer {token}
Content-Type: application/json
{
"exercises": [
{
"key": "warmup_dynamic",
"name": "动态热身",
"category": "热身",
"durationSec": 300,
"itemType": "exercise",
"note": "轻松活动关节,准备训练"
},
{
"key": "note_safety",
"name": "安全提醒",
"note": "如感到不适请立即停止,保持正确呼吸",
"itemType": "note"
},
{
"key": "squat_exercise",
"name": "深蹲训练",
"category": "下肢力量",
"sets": 3,
"reps": 15,
"restSec": 60,
"itemType": "exercise",
"note": "下蹲时膝盖不超过脚尖"
},
{
"key": "rest_squat",
"name": "组间休息",
"durationSec": 90,
"itemType": "rest"
},
{
"key": "pushup_exercise",
"name": "俯卧撑",
"category": "上肢力量",
"sets": 3,
"reps": 12,
"restSec": 60,
"itemType": "exercise",
"note": "保持身体一条直线"
},
{
"key": "rest_pushup",
"name": "组间休息",
"durationSec": 90,
"itemType": "rest"
},
{
"key": "plank_exercise",
"name": "平板支撑",
"category": "核心力量",
"sets": 3,
"durationSec": 60,
"restSec": 45,
"itemType": "exercise",
"note": "腹部收紧,不要塌腰"
},
{
"key": "cooldown_stretch",
"name": "拉伸放松",
"category": "拉伸",
"durationSec": 600,
"itemType": "exercise",
"note": "充分拉伸训练过的肌群"
}
]
}
```
响应:
```json
[
{
"id": "ex_1705123456790_def456",
"trainingPlanId": "plan_1705123456789_abc123",
"key": "warmup_dynamic",
"name": "动态热身",
"category": "热身",
"sets": 0,
"durationSec": 300,
"note": "轻松活动关节,准备训练",
"itemType": "exercise",
"completed": false,
"sortOrder": 1,
"createdAt": "2024-01-10T10:35:00.000Z",
"updatedAt": "2024-01-10T10:35:00.000Z"
},
// ... 其他项目
]
```
### 3. 获取训练项目列表
```bash
GET /training-plans/plan_1705123456789_abc123/exercises
Authorization: Bearer {token}
```
响应按sortOrder排序的完整项目列表
```json
[
{
"id": "ex_1705123456790_def456",
"trainingPlanId": "plan_1705123456789_abc123",
"key": "warmup_dynamic",
"name": "动态热身",
"category": "热身",
"sets": 0,
"durationSec": 300,
"note": "轻松活动关节,准备训练",
"itemType": "exercise",
"completed": false,
"sortOrder": 1
},
{
"id": "ex_1705123456791_ghi789",
"trainingPlanId": "plan_1705123456789_abc123",
"key": "note_safety",
"name": "安全提醒",
"note": "如感到不适请立即停止,保持正确呼吸",
"itemType": "note",
"completed": false,
"sortOrder": 2
}
// ... 更多项目
]
```
### 4. 用户完成训练项目
```bash
PUT /training-plans/plan_1705123456789_abc123/exercises/ex_1705123456792_jkl012/complete
Authorization: Bearer {token}
Content-Type: application/json
{
"completed": true
}
```
响应:
```json
{
"id": "ex_1705123456792_jkl012",
"trainingPlanId": "plan_1705123456789_abc123",
"key": "squat_exercise",
"name": "深蹲训练",
"category": "下肢力量",
"sets": 3,
"reps": 15,
"restSec": 60,
"itemType": "exercise",
"completed": true,
"sortOrder": 3,
"updatedAt": "2024-01-10T11:15:00.000Z"
}
```
### 5. 调整训练项目顺序
```bash
PUT /training-plans/plan_1705123456789_abc123/exercises/order
Authorization: Bearer {token}
Content-Type: application/json
{
"exerciseIds": [
"ex_1705123456790_def456", // 热身
"ex_1705123456792_jkl012", // 深蹲 (提前)
"ex_1705123456791_ghi789", // 安全提醒 (延后)
"ex_1705123456793_mno345", // 休息
"ex_1705123456794_pqr678" // 其他项目...
]
}
```
响应:
```json
{
"success": true
}
```
### 6. 批量更新训练强度
```bash
PUT /training-plans/plan_1705123456789_abc123/exercises/batch
Authorization: Bearer {token}
Content-Type: application/json
{
"exercises": [
{
"id": "ex_1705123456792_jkl012",
"sets": 4, // 增加组数
"reps": 18 // 增加次数
},
{
"id": "ex_1705123456794_pqr678",
"sets": 4,
"reps": 15
},
{
"id": "ex_1705123456795_stu901",
"durationSec": 75 // 增加平板支撑时长
}
]
}
```
### 7. 查看训练完成统计
```bash
GET /training-plans/plan_1705123456789_abc123/exercises/stats/completion
Authorization: Bearer {token}
```
响应:
```json
{
"total": 5, // 总共5个运动项目(不包括休息和提醒)
"completed": 3, // 已完成3个
"percentage": 60 // 完成率60%
}
```
### 8. 删除不需要的项目
```bash
DELETE /training-plans/plan_1705123456789_abc123/exercises
Authorization: Bearer {token}
Content-Type: application/json
[
"ex_1705123456793_mno345", // 删除某个休息项目
"ex_1705123456796_vwx234" // 删除某个提醒项目
]
```
响应:
```json
{
"success": true,
"deletedCount": 2
}
```
## 错误处理示例
### 重复的key错误
```bash
POST /training-plans/plan_1705123456789_abc123/exercises
{
"key": "squat_exercise", // 已存在的key
"name": "新的深蹲"
}
```
响应:
```json
{
"statusCode": 400,
"message": "项目key \"squat_exercise\" 已存在",
"error": "Bad Request"
}
```
### 训练计划不存在
```bash
GET /training-plans/nonexistent_plan/exercises
```
响应:
```json
{
"statusCode": 404,
"message": "训练计划不存在或不属于当前用户",
"error": "Not Found"
}
```
## 前端集成建议
### 1. 训练项目组件状态管理
```typescript
interface TrainingSessionState {
exercises: ScheduleExercise[];
currentExercise: number;
completedCount: number;
totalCount: number;
}
// 加载训练项目
const loadExercises = async (planId: string) => {
const exercises = await api.get(`/training-plans/${planId}/exercises`);
return exercises.filter(ex => ex.itemType === 'exercise');
};
// 标记完成
const markComplete = async (planId: string, exerciseId: string) => {
await api.put(`/training-plans/${planId}/exercises/${exerciseId}/complete`, {
completed: true
});
};
```
### 2. 拖拽重新排序
```typescript
const handleDragEnd = async (result: DropResult) => {
if (!result.destination) return;
const newOrder = Array.from(exercises);
const [reorderedItem] = newOrder.splice(result.source.index, 1);
newOrder.splice(result.destination.index, 0, reorderedItem);
const exerciseIds = newOrder.map(ex => ex.id);
await api.put(`/training-plans/${planId}/exercises/order`, {
exerciseIds
});
setExercises(newOrder);
};
```
这个API设计提供了完整的训练项目管理功能支持用户创建个性化的训练流程实时跟踪完成进度并且具有良好的扩展性。