Files
plates-server/src/workouts/dto/workout-exercise.dto.ts
richarjiang 0edcfdcae9 新增普拉提训练系统的数据库结构和数据导入功能
- 创建普拉提分类和动作数据的SQL导入脚本,支持垫上普拉提和器械普拉提的分类管理
- 实现数据库结构迁移脚本,添加新字段以支持普拉提类型和器械名称
- 更新数据库升级总结文档,详细说明数据库结构变更和数据导入步骤
- 创建训练会话相关表,支持每日训练实例功能
- 引入训练会话管理模块,整合训练计划与实际训练会话的关系
2025-08-15 15:34:11 +08:00

171 lines
4.8 KiB
TypeScript
Raw 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.

import { ApiProperty, PartialType } from '@nestjs/swagger';
import { IsArray, IsBoolean, IsDateString, IsEnum, IsInt, IsNotEmpty, IsOptional, IsString, IsUUID, Min, Max } from 'class-validator';
import { WorkoutItemType, WorkoutExerciseStatus } from '../models/workout-exercise.model';
export class CreateWorkoutExerciseDto {
@ApiProperty({ description: '关联的动作key仅exercise类型需要', required: false })
@IsString()
@IsOptional()
exerciseKey?: string;
@ApiProperty({ description: '项目名称' })
@IsString()
@IsNotEmpty()
name: string;
@ApiProperty({ description: '计划组数', required: false })
@IsInt()
@Min(0)
@IsOptional()
plannedSets?: number;
@ApiProperty({ description: '计划重复次数', required: false })
@IsInt()
@Min(0)
@IsOptional()
plannedReps?: number;
@ApiProperty({ description: '计划持续时长(秒)', required: false })
@IsInt()
@Min(0)
@IsOptional()
plannedDurationSec?: number;
@ApiProperty({ description: '休息时长(秒)', required: false })
@IsInt()
@Min(0)
@IsOptional()
restSec?: number;
@ApiProperty({ description: '备注', required: false })
@IsString()
@IsOptional()
note?: string;
@ApiProperty({
enum: ['exercise', 'rest', 'note'],
description: '项目类型',
default: 'exercise',
required: false
})
@IsEnum(['exercise', 'rest', 'note'])
@IsOptional()
itemType?: WorkoutItemType;
}
export class UpdateWorkoutExerciseDto extends PartialType(CreateWorkoutExerciseDto) {
@ApiProperty({ description: '实际完成组数', required: false })
@IsInt()
@Min(0)
@IsOptional()
completedSets?: number;
@ApiProperty({ description: '实际完成重复次数', required: false })
@IsInt()
@Min(0)
@IsOptional()
completedReps?: number;
@ApiProperty({ description: '实际持续时长(秒)', required: false })
@IsInt()
@Min(0)
@IsOptional()
actualDurationSec?: number;
@ApiProperty({ enum: ['pending', 'in_progress', 'completed', 'skipped'], required: false })
@IsEnum(['pending', 'in_progress', 'completed', 'skipped'])
@IsOptional()
status?: WorkoutExerciseStatus;
}
export class StartWorkoutExerciseDto {
@ApiProperty({ description: '开始时间', required: false })
@IsDateString()
@IsOptional()
startedAt?: string;
}
export class CompleteWorkoutExerciseDto {
@ApiProperty({ description: '实际完成组数', required: false })
@IsInt()
@Min(0)
@IsOptional()
completedSets?: number;
@ApiProperty({ description: '实际完成重复次数', required: false })
@IsInt()
@Min(0)
@IsOptional()
completedReps?: number;
@ApiProperty({ description: '实际持续时长(秒)', required: false })
@IsInt()
@Min(0)
@IsOptional()
actualDurationSec?: number;
@ApiProperty({ description: '完成时间', required: false })
@IsDateString()
@IsOptional()
completedAt?: string;
@ApiProperty({ description: '详细执行数据', required: false })
@IsOptional()
performanceData?: {
sets?: Array<{
reps?: number;
weight?: number;
duration?: number;
restTime?: number;
difficulty?: number;
notes?: string;
}>;
heartRate?: {
avg?: number;
max?: number;
};
perceivedExertion?: number;
};
}
export class UpdateWorkoutExerciseOrderDto {
@ApiProperty({ description: '动作ID列表按新的顺序排列' })
@IsArray()
@IsString({ each: true })
exerciseIds: string[];
}
export class WorkoutExerciseResponseDto {
@ApiProperty() id: string;
@ApiProperty() workoutSessionId: string;
@ApiProperty() userId: string;
@ApiProperty({ required: false }) exerciseKey?: string;
@ApiProperty() name: string;
@ApiProperty({ required: false }) plannedSets?: number;
@ApiProperty({ required: false }) completedSets?: number;
@ApiProperty({ required: false }) plannedReps?: number;
@ApiProperty({ required: false }) completedReps?: number;
@ApiProperty({ required: false }) plannedDurationSec?: number;
@ApiProperty({ required: false }) actualDurationSec?: number;
@ApiProperty({ required: false }) restSec?: number;
@ApiProperty({ required: false }) note?: string;
@ApiProperty({ enum: ['exercise', 'rest', 'note'] }) itemType: WorkoutItemType;
@ApiProperty({ enum: ['pending', 'in_progress', 'completed', 'skipped'] }) status: WorkoutExerciseStatus;
@ApiProperty() sortOrder: number;
@ApiProperty({ required: false }) startedAt?: Date;
@ApiProperty({ required: false }) completedAt?: Date;
@ApiProperty({ required: false }) performanceData?: any;
@ApiProperty() createdAt: Date;
@ApiProperty() updatedAt: Date;
// 关联的动作信息仅exercise类型时存在
@ApiProperty({ required: false })
exercise?: {
key: string;
name: string;
description: string;
categoryKey: string;
categoryName: string;
};
}