Files
plates-server/docs/training-plans-optimization-summary.md
richarjiang bea71af5d3 优化训练计划项目管理功能
- 更新训练项目文档,增加与动作库的智能关联和简化接口操作的说明
- 移除批量操作接口,专注于单项操作,提升用户体验
- 增强数据模型,确保训练项目与动作库的关联性,提升数据一致性和查询性能
- 更新服务逻辑,支持动作存在性验证,确保数据的准确性和完整性
2025-08-15 11:37:11 +08:00

201 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 训练计划项目管理系统优化总结
## 优化背景
原始设计存在以下问题:
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. **扩展性**: 为未来的功能扩展提供了良好的架构基础
这个优化后的设计既保持了功能的完整性,又显著提升了系统的可维护性和用户体验。