新增普拉提训练系统的数据库结构和数据导入功能
- 创建普拉提分类和动作数据的SQL导入脚本,支持垫上普拉提和器械普拉提的分类管理 - 实现数据库结构迁移脚本,添加新字段以支持普拉提类型和器械名称 - 更新数据库升级总结文档,详细说明数据库结构变更和数据导入步骤 - 创建训练会话相关表,支持每日训练实例功能 - 引入训练会话管理模块,整合训练计划与实际训练会话的关系
This commit is contained in:
@@ -17,7 +17,7 @@ export class ScheduleExercise extends Model {
|
||||
declare id: string;
|
||||
|
||||
@ForeignKey(() => TrainingPlan)
|
||||
@Column({ type: DataType.STRING, allowNull: false })
|
||||
@Column({ type: DataType.UUID, allowNull: false })
|
||||
declare trainingPlanId: string;
|
||||
|
||||
@BelongsTo(() => TrainingPlan)
|
||||
|
||||
@@ -6,8 +6,7 @@ import { Exercise } from '../exercises/models/exercise.model';
|
||||
import {
|
||||
CreateScheduleExerciseDto,
|
||||
UpdateScheduleExerciseDto,
|
||||
UpdateScheduleExerciseOrderDto,
|
||||
CompleteScheduleExerciseDto
|
||||
UpdateScheduleExerciseOrderDto
|
||||
} from './dto/schedule-exercise.dto';
|
||||
import { ActivityLogsService } from '../activity-logs/activity-logs.service';
|
||||
import { ActivityActionType, ActivityEntityType } from '../activity-logs/models/activity-log.model';
|
||||
@@ -299,60 +298,7 @@ export class ScheduleExerciseService {
|
||||
}
|
||||
}
|
||||
|
||||
// 标记完成状态
|
||||
async markComplete(userId: string, trainingPlanId: string, exerciseId: string, dto: CompleteScheduleExerciseDto) {
|
||||
await this.validateTrainingPlan(userId, trainingPlanId);
|
||||
|
||||
const exercise = await this.scheduleExerciseModel.findOne({
|
||||
where: { id: exerciseId, trainingPlanId, userId, deleted: false }
|
||||
});
|
||||
|
||||
if (!exercise) {
|
||||
throw new NotFoundException('训练项目不存在');
|
||||
}
|
||||
|
||||
const before = exercise.completed;
|
||||
exercise.completed = dto.completed;
|
||||
await exercise.save();
|
||||
|
||||
await this.activityLogsService.record({
|
||||
userId,
|
||||
entityType: ActivityEntityType.TRAINING_PLAN,
|
||||
action: ActivityActionType.UPDATE,
|
||||
entityId: exerciseId,
|
||||
changes: {
|
||||
completed: { before, after: dto.completed }
|
||||
},
|
||||
});
|
||||
|
||||
this.winstonLogger.info(`标记训练项目完成状态 ${exerciseId}: ${dto.completed}`, {
|
||||
context: 'ScheduleExerciseService',
|
||||
userId,
|
||||
trainingPlanId,
|
||||
exerciseId,
|
||||
completed: dto.completed,
|
||||
});
|
||||
|
||||
return exercise.toJSON();
|
||||
}
|
||||
|
||||
// 获取训练计划的完成统计
|
||||
async getCompletionStats(userId: string, trainingPlanId: string) {
|
||||
await this.validateTrainingPlan(userId, trainingPlanId);
|
||||
|
||||
const [total, completed] = await Promise.all([
|
||||
this.scheduleExerciseModel.count({
|
||||
where: { trainingPlanId, userId, deleted: false, itemType: 'exercise' }
|
||||
}),
|
||||
this.scheduleExerciseModel.count({
|
||||
where: { trainingPlanId, userId, deleted: false, itemType: 'exercise', completed: true }
|
||||
})
|
||||
]);
|
||||
|
||||
return {
|
||||
total,
|
||||
completed,
|
||||
percentage: total > 0 ? Math.round((completed / total) * 100) : 0
|
||||
};
|
||||
}
|
||||
// 注意:训练计划是模板,不应该有完成状态
|
||||
// 训练完成状态应该在 WorkoutSession 和 WorkoutExercise 中管理
|
||||
// 如需标记完成状态,请使用 WorkoutsService
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
CreateScheduleExerciseDto,
|
||||
UpdateScheduleExerciseDto,
|
||||
UpdateScheduleExerciseOrderDto,
|
||||
CompleteScheduleExerciseDto,
|
||||
ScheduleExerciseResponseDto
|
||||
} from './dto/schedule-exercise.dto';
|
||||
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
|
||||
@@ -153,29 +152,9 @@ export class TrainingPlansController {
|
||||
return this.scheduleExerciseService.updateOrder(user.sub, trainingPlanId, dto);
|
||||
}
|
||||
|
||||
@Put(':id/exercises/:exerciseId/complete')
|
||||
@ApiOperation({ summary: '标记训练项目完成状态' })
|
||||
@ApiParam({ name: 'id', description: '训练计划ID' })
|
||||
@ApiParam({ name: 'exerciseId', description: '训练项目ID' })
|
||||
@ApiBody({ type: CompleteScheduleExerciseDto })
|
||||
async markExerciseComplete(
|
||||
@CurrentUser() user: AccessTokenPayload,
|
||||
@Param('id') trainingPlanId: string,
|
||||
@Param('exerciseId') exerciseId: string,
|
||||
@Body() dto: CompleteScheduleExerciseDto,
|
||||
) {
|
||||
return this.scheduleExerciseService.markComplete(user.sub, trainingPlanId, exerciseId, dto);
|
||||
}
|
||||
|
||||
@Get(':id/exercises/stats/completion')
|
||||
@ApiOperation({ summary: '获取训练计划完成统计' })
|
||||
@ApiParam({ name: 'id', description: '训练计划ID' })
|
||||
async getExerciseCompletionStats(
|
||||
@CurrentUser() user: AccessTokenPayload,
|
||||
@Param('id') trainingPlanId: string,
|
||||
) {
|
||||
return this.scheduleExerciseService.getCompletionStats(user.sub, trainingPlanId);
|
||||
}
|
||||
// 注意:训练计划是模板,不应该有完成状态
|
||||
// 实际的训练完成状态应该在 WorkoutSession 中管理
|
||||
// 如需完成训练,请使用 /workouts/sessions 相关接口
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user