- 更新训练项目文档,增加与动作库的智能关联和简化接口操作的说明 - 移除批量操作接口,专注于单项操作,提升用户体验 - 增强数据模型,确保训练项目与动作库的关联性,提升数据一致性和查询性能 - 更新服务逻辑,支持动作存在性验证,确保数据的准确性和完整性
5.5 KiB
5.5 KiB
训练计划项目管理系统优化总结
优化背景
原始设计存在以下问题:
- 训练项目与系统动作库缺乏关联
- 接口复杂,包含过多批量操作
- 数据结构冗余,缺乏标准化
核心优化
1. 数据库模型优化
之前的设计
// 独立的项目标识,与动作库无关联
interface ScheduleExercise {
key: string; // 自定义项目key
name: string; // 自定义名称
category?: string; // 自定义分类
// ...
}
优化后的设计
// 智能关联动作库的设计
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. 业务逻辑优化
智能验证机制
// 动作存在性验证
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);
}
关联数据获取
// 查询时自动包含动作信息
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. 动作选择组件
// 获取可用动作列表
const exercises = await api.get('/exercises/config');
// 创建训练项目时选择动作
const createExercise = {
exerciseKey: selectedExercise.key, // 从动作库选择
name: customName || selectedExercise.name, // 可自定义名称
sets: 3,
reps: 15,
itemType: 'exercise'
};
2. 数据显示组件
// 显示训练项目时同时展示动作详情
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. 操作流程优化
// 简化的操作流程
const addExercise = async (exerciseKey, customParams) => {
const exercise = await api.post(`/training-plans/${planId}/exercises`, {
exerciseKey,
...customParams
});
// 无需额外查询,响应已包含完整信息
updateExerciseList(exercise);
};
总结
这次优化重点解决了数据关联和接口复杂度两大核心问题:
- 智能关联: 通过外键关联确保训练项目与动作库的数据一致性
- 接口简化: 去除批量操作,专注于单项操作的用户体验
- 性能优化: 通过关联查询减少API调用次数
- 扩展性: 为未来的功能扩展提供了良好的架构基础
这个优化后的设计既保持了功能的完整性,又显著提升了系统的可维护性和用户体验。