优化训练计划项目管理功能
- 更新训练项目文档,增加与动作库的智能关联和简化接口操作的说明 - 移除批量操作接口,专注于单项操作,提升用户体验 - 增强数据模型,确保训练项目与动作库的关联性,提升数据一致性和查询性能 - 更新服务逻辑,支持动作存在性验证,确保数据的准确性和完整性
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
# 训练计划项目管理 API 使用示例
|
||||
# 训练计划项目管理 API 使用示例(优化版)
|
||||
|
||||
这个版本展示了优化后的 API 设计,重点是与动作库的智能关联和简化的接口操作。
|
||||
|
||||
## 创建一个完整的训练计划项目
|
||||
|
||||
@@ -35,139 +37,169 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 批量添加训练项目
|
||||
### 2. 逐个添加训练项目(关联动作库)
|
||||
|
||||
#### 添加热身项目
|
||||
```bash
|
||||
POST /training-plans/plan_1705123456789_abc123/exercises/batch
|
||||
POST /training-plans/plan_1705123456789_abc123/exercises
|
||||
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": "充分拉伸训练过的肌群"
|
||||
}
|
||||
]
|
||||
"exerciseKey": "dynamic_warmup", // 关联动作库中的动态热身
|
||||
"name": "动态热身",
|
||||
"durationSec": 300,
|
||||
"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"
|
||||
},
|
||||
// ... 其他项目
|
||||
]
|
||||
#### 添加安全提醒
|
||||
```bash
|
||||
POST /training-plans/plan_1705123456789_abc123/exercises
|
||||
Authorization: Bearer {token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "安全提醒",
|
||||
"note": "如感到不适请立即停止,保持正确呼吸",
|
||||
"itemType": "note"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 获取训练项目列表
|
||||
#### 添加深蹲训练
|
||||
```bash
|
||||
POST /training-plans/plan_1705123456789_abc123/exercises
|
||||
Authorization: Bearer {token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exerciseKey": "squat", // 关联动作库中的深蹲
|
||||
"name": "深蹲训练",
|
||||
"sets": 3,
|
||||
"reps": 15,
|
||||
"restSec": 60,
|
||||
"itemType": "exercise",
|
||||
"note": "下蹲时膝盖不超过脚尖"
|
||||
}
|
||||
```
|
||||
|
||||
#### 添加休息时间
|
||||
```bash
|
||||
POST /training-plans/plan_1705123456789_abc123/exercises
|
||||
Authorization: Bearer {token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "组间休息",
|
||||
"durationSec": 90,
|
||||
"itemType": "rest"
|
||||
}
|
||||
```
|
||||
|
||||
#### 添加俯卧撑训练
|
||||
```bash
|
||||
POST /training-plans/plan_1705123456789_abc123/exercises
|
||||
Authorization: Bearer {token}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exerciseKey": "pushup", // 关联动作库中的俯卧撑
|
||||
"name": "俯卧撑训练",
|
||||
"sets": 3,
|
||||
"reps": 12,
|
||||
"restSec": 60,
|
||||
"itemType": "exercise",
|
||||
"note": "保持身体一条直线"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
每个添加请求的响应示例:
|
||||
```json
|
||||
{
|
||||
"id": "ex_1705123456790_def456",
|
||||
"trainingPlanId": "plan_1705123456789_abc123",
|
||||
"exerciseKey": "squat",
|
||||
"name": "深蹲训练",
|
||||
"sets": 3,
|
||||
"reps": 15,
|
||||
"restSec": 60,
|
||||
"note": "下蹲时膝盖不超过脚尖",
|
||||
"itemType": "exercise",
|
||||
"completed": false,
|
||||
"sortOrder": 3,
|
||||
"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排序的完整项目列表
|
||||
响应:按sortOrder排序的完整项目列表,包含关联的动作信息
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "ex_1705123456790_def456",
|
||||
"trainingPlanId": "plan_1705123456789_abc123",
|
||||
"key": "warmup_dynamic",
|
||||
"exerciseKey": "dynamic_warmup",
|
||||
"name": "动态热身",
|
||||
"category": "热身",
|
||||
"sets": 0,
|
||||
"durationSec": 300,
|
||||
"note": "轻松活动关节,准备训练",
|
||||
"itemType": "exercise",
|
||||
"completed": false,
|
||||
"sortOrder": 1
|
||||
"sortOrder": 1,
|
||||
"exercise": {
|
||||
"key": "dynamic_warmup",
|
||||
"name": "动态热身",
|
||||
"description": "通过各种动态动作激活身体,为训练做准备",
|
||||
"categoryKey": "warmup",
|
||||
"categoryName": "热身"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ex_1705123456791_ghi789",
|
||||
"trainingPlanId": "plan_1705123456789_abc123",
|
||||
"key": "note_safety",
|
||||
"name": "安全提醒",
|
||||
"note": "如感到不适请立即停止,保持正确呼吸",
|
||||
"itemType": "note",
|
||||
"completed": false,
|
||||
"sortOrder": 2
|
||||
},
|
||||
{
|
||||
"id": "ex_1705123456792_jkl012",
|
||||
"trainingPlanId": "plan_1705123456789_abc123",
|
||||
"exerciseKey": "squat",
|
||||
"name": "深蹲训练",
|
||||
"sets": 3,
|
||||
"reps": 15,
|
||||
"restSec": 60,
|
||||
"note": "下蹲时膝盖不超过脚尖",
|
||||
"itemType": "exercise",
|
||||
"completed": false,
|
||||
"sortOrder": 3,
|
||||
"exercise": {
|
||||
"key": "squat",
|
||||
"name": "深蹲",
|
||||
"description": "下肢力量训练的基础动作,主要锻炼大腿和臀部肌肉",
|
||||
"categoryKey": "strength",
|
||||
"categoryName": "力量训练"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ex_1705123456793_mno345",
|
||||
"trainingPlanId": "plan_1705123456789_abc123",
|
||||
"name": "组间休息",
|
||||
"durationSec": 90,
|
||||
"itemType": "rest",
|
||||
"completed": false,
|
||||
"sortOrder": 4
|
||||
}
|
||||
// ... 更多项目
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
200
docs/training-plans-optimization-summary.md
Normal file
200
docs/training-plans-optimization-summary.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# 训练计划项目管理系统优化总结
|
||||
|
||||
## 优化背景
|
||||
|
||||
原始设计存在以下问题:
|
||||
1. 训练项目与系统动作库缺乏关联
|
||||
2. 接口复杂,包含过多批量操作
|
||||
3. 数据结构冗余,缺乏标准化
|
||||
|
||||
## 核心优化
|
||||
|
||||
### 1. 数据库模型优化
|
||||
|
||||
#### 之前的设计
|
||||
```typescript
|
||||
// 独立的项目标识,与动作库无关联
|
||||
interface ScheduleExercise {
|
||||
key: string; // 自定义项目key
|
||||
name: string; // 自定义名称
|
||||
category?: string; // 自定义分类
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 优化后的设计
|
||||
```typescript
|
||||
// 智能关联动作库的设计
|
||||
interface ScheduleExercise {
|
||||
exerciseKey?: string; // 关联动作库(外键)
|
||||
name: string; // 可自定义的名称
|
||||
// ...
|
||||
exercise?: { // 关联的动作信息
|
||||
key: string;
|
||||
name: string;
|
||||
description: string;
|
||||
categoryKey: string;
|
||||
categoryName: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### 数据库关系
|
||||
- `ScheduleExercise.exerciseKey` → `Exercise.key` (外键关联)
|
||||
- 支持左连接查询,获取完整动作信息
|
||||
- exercise类型项目必须关联动作库,rest/note类型可选
|
||||
|
||||
### 2. 接口设计简化
|
||||
|
||||
#### 去除的批量操作接口
|
||||
- ❌ `POST /exercises/batch` - 批量创建
|
||||
- ❌ `PUT /exercises/batch` - 批量更新
|
||||
- ❌ `DELETE /exercises` - 批量删除
|
||||
|
||||
#### 保留的核心接口
|
||||
- ✅ `POST /exercises` - 单个创建
|
||||
- ✅ `GET /exercises` - 列表查询
|
||||
- ✅ `GET /exercises/:id` - 详情查询
|
||||
- ✅ `PUT /exercises/:id` - 单个更新
|
||||
- ✅ `DELETE /exercises/:id` - 单个删除
|
||||
- ✅ `PUT /exercises/order` - 排序调整
|
||||
- ✅ `PUT /exercises/:id/complete` - 完成状态
|
||||
- ✅ `GET /exercises/stats/completion` - 统计信息
|
||||
|
||||
### 3. 业务逻辑优化
|
||||
|
||||
#### 智能验证机制
|
||||
```typescript
|
||||
// 动作存在性验证
|
||||
private async validateExercise(exerciseKey: string) {
|
||||
const exercise = await this.exerciseModel.findByPk(exerciseKey);
|
||||
if (!exercise) {
|
||||
throw new NotFoundException(`动作 "${exerciseKey}" 不存在`);
|
||||
}
|
||||
return exercise;
|
||||
}
|
||||
|
||||
// 创建时的验证逻辑
|
||||
if (dto.itemType === 'exercise' && dto.exerciseKey) {
|
||||
await this.validateExercise(dto.exerciseKey);
|
||||
}
|
||||
```
|
||||
|
||||
#### 关联数据获取
|
||||
```typescript
|
||||
// 查询时自动包含动作信息
|
||||
const exercises = await this.scheduleExerciseModel.findAll({
|
||||
include: [{ model: Exercise, required: false }],
|
||||
order: [['sortOrder', 'ASC']],
|
||||
});
|
||||
|
||||
// 格式化返回数据
|
||||
return exercises.map(exercise => ({
|
||||
...exercise.toJSON(),
|
||||
exercise: exercise.exercise ? {
|
||||
key: exercise.exercise.key,
|
||||
name: exercise.exercise.name,
|
||||
description: exercise.exercise.description,
|
||||
categoryKey: exercise.exercise.categoryKey,
|
||||
categoryName: exercise.exercise.categoryName,
|
||||
} : undefined
|
||||
}));
|
||||
```
|
||||
|
||||
## 技术收益
|
||||
|
||||
### 1. 数据一致性提升
|
||||
- ✅ 动作信息标准化,避免重复维护
|
||||
- ✅ 外键约束确保数据完整性
|
||||
- ✅ 动作库统一管理,便于更新
|
||||
|
||||
### 2. 接口复杂度降低
|
||||
- ✅ 去除批量操作,专注单项操作
|
||||
- ✅ 接口数量从11个减少到8个
|
||||
- ✅ 参数验证逻辑简化
|
||||
|
||||
### 3. 查询性能优化
|
||||
- ✅ 左连接一次性获取完整信息
|
||||
- ✅ 减少前端多次API调用
|
||||
- ✅ 数据库索引优化
|
||||
|
||||
### 4. 扩展性增强
|
||||
- ✅ 新增动作自动可用于训练计划
|
||||
- ✅ 动作分类变更自动同步
|
||||
- ✅ 支持动作版本管理
|
||||
|
||||
## 业务价值
|
||||
|
||||
### 1. 用户体验改善
|
||||
- **专业性提升**: 基于标准动作库,确保训练的专业性
|
||||
- **操作简化**: 单项操作更直观,降低学习成本
|
||||
- **信息完整**: 自动获取动作描述、分类等详细信息
|
||||
|
||||
### 2. 内容管理优化
|
||||
- **集中管理**: 动作库统一维护,避免内容重复
|
||||
- **质量控制**: 标准化的动作描述和分类
|
||||
- **版本控制**: 支持动作信息的统一更新
|
||||
|
||||
### 3. 开发效率提升
|
||||
- **接口简化**: 减少API数量,降低维护成本
|
||||
- **类型安全**: 强类型验证,减少运行时错误
|
||||
- **测试简化**: 单项操作更容易编写测试用例
|
||||
|
||||
## 前端适配建议
|
||||
|
||||
### 1. 动作选择组件
|
||||
```typescript
|
||||
// 获取可用动作列表
|
||||
const exercises = await api.get('/exercises/config');
|
||||
|
||||
// 创建训练项目时选择动作
|
||||
const createExercise = {
|
||||
exerciseKey: selectedExercise.key, // 从动作库选择
|
||||
name: customName || selectedExercise.name, // 可自定义名称
|
||||
sets: 3,
|
||||
reps: 15,
|
||||
itemType: 'exercise'
|
||||
};
|
||||
```
|
||||
|
||||
### 2. 数据显示组件
|
||||
```typescript
|
||||
// 显示训练项目时同时展示动作详情
|
||||
const ExerciseItem = ({ item }) => (
|
||||
<div>
|
||||
<h3>{item.name}</h3>
|
||||
{item.exercise && (
|
||||
<div>
|
||||
<p>分类: {item.exercise.categoryName}</p>
|
||||
<p>说明: {item.exercise.description}</p>
|
||||
</div>
|
||||
)}
|
||||
<p>组数: {item.sets} | 次数: {item.reps}</p>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
### 3. 操作流程优化
|
||||
```typescript
|
||||
// 简化的操作流程
|
||||
const addExercise = async (exerciseKey, customParams) => {
|
||||
const exercise = await api.post(`/training-plans/${planId}/exercises`, {
|
||||
exerciseKey,
|
||||
...customParams
|
||||
});
|
||||
|
||||
// 无需额外查询,响应已包含完整信息
|
||||
updateExerciseList(exercise);
|
||||
};
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
这次优化重点解决了数据关联和接口复杂度两大核心问题:
|
||||
|
||||
1. **智能关联**: 通过外键关联确保训练项目与动作库的数据一致性
|
||||
2. **接口简化**: 去除批量操作,专注于单项操作的用户体验
|
||||
3. **性能优化**: 通过关联查询减少API调用次数
|
||||
4. **扩展性**: 为未来的功能扩展提供了良好的架构基础
|
||||
|
||||
这个优化后的设计既保持了功能的完整性,又显著提升了系统的可维护性和用户体验。
|
||||
Reference in New Issue
Block a user