| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- import { Repository } from 'typeorm';
- import { v4 as uuidv4 } from 'uuid';
- import { AppDataSource } from '../config/database';
- import { WeightGoal, GoalStatus } from '../entities/WeightGoal';
- import { WeightRecord } from '../entities/WeightRecord';
- import { CreateWeightGoalDto, UpdateWeightGoalDto } from '../dto/weight-goal.dto';
- export class WeightGoalService {
- private weightGoalRepository: Repository<WeightGoal>;
- private weightRecordRepository: Repository<WeightRecord>;
- constructor() {
- this.weightGoalRepository = AppDataSource.getRepository(WeightGoal);
- this.weightRecordRepository = AppDataSource.getRepository(WeightRecord);
- }
- /**
- * 创建体重目标
- */
- async createGoal(userId: string, dto: CreateWeightGoalDto): Promise<WeightGoal> {
- // 获取用户最新体重记录
- const latestRecord = await this.weightRecordRepository.findOne({
- where: { userId },
- order: { recordDate: 'DESC', createdAt: 'DESC' }
- });
- if (!latestRecord) {
- throw new Error('请先添加体重记录');
- }
- // 将之前的活跃目标标记为已放弃
- await this.weightGoalRepository.update(
- { userId, status: GoalStatus.ACTIVE },
- { status: GoalStatus.ABANDONED }
- );
- // 计算每周目标
- const startDate = new Date(latestRecord.recordDate);
- const targetDate = new Date(dto.targetDate);
- const daysDiff = Math.ceil((targetDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
- const weeksDiff = daysDiff / 7;
- const weightDiff = Math.abs(Number(latestRecord.weight) - dto.targetWeight);
- const weeklyTarget = weeksDiff > 0 ? Number((weightDiff / weeksDiff).toFixed(2)) : 0;
- // 创建新目标
- const goal = this.weightGoalRepository.create({
- id: uuidv4(),
- userId,
- targetWeight: dto.targetWeight,
- targetBodyFat: dto.targetBodyFat || null,
- targetDate: dto.targetDate,
- startWeight: Number(latestRecord.weight),
- startBodyFat: Number(latestRecord.bodyFat),
- startDate: latestRecord.recordDate,
- weeklyTarget,
- status: GoalStatus.ACTIVE
- });
- await this.weightGoalRepository.save(goal);
- return goal;
- }
- /**
- * 更新体重目标
- */
- async updateGoal(userId: string, dto: UpdateWeightGoalDto): Promise<WeightGoal> {
- const goal = await this.weightGoalRepository.findOne({
- where: { userId, status: GoalStatus.ACTIVE }
- });
- if (!goal) {
- throw new Error('未找到活跃的目标');
- }
- // 更新目标
- if (dto.targetWeight !== undefined) goal.targetWeight = dto.targetWeight;
- if (dto.targetBodyFat !== undefined) goal.targetBodyFat = dto.targetBodyFat;
- if (dto.targetDate !== undefined) goal.targetDate = dto.targetDate;
- // 重新计算每周目标
- if (dto.targetWeight !== undefined || dto.targetDate !== undefined) {
- const startDate = new Date(goal.startDate);
- const targetDate = new Date(goal.targetDate);
- const daysDiff = Math.ceil((targetDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
- const weeksDiff = daysDiff / 7;
- const weightDiff = Math.abs(Number(goal.startWeight) - goal.targetWeight);
- goal.weeklyTarget = weeksDiff > 0 ? Number((weightDiff / weeksDiff).toFixed(2)) : 0;
- }
- await this.weightGoalRepository.save(goal);
- return goal;
- }
- /**
- * 获取当前活跃目标
- */
- async getCurrentGoal(userId: string): Promise<WeightGoal | null> {
- const goal = await this.weightGoalRepository.findOne({
- where: { userId, status: GoalStatus.ACTIVE },
- order: { createdAt: 'DESC' }
- });
- return goal;
- }
- /**
- * 格式化目标输出
- */
- formatGoal(goal: WeightGoal): any {
- return {
- id: goal.id,
- targetWeight: Number(goal.targetWeight),
- targetBodyFat: goal.targetBodyFat ? Number(goal.targetBodyFat) : null,
- targetDate: goal.targetDate,
- startWeight: Number(goal.startWeight),
- startBodyFat: goal.startBodyFat ? Number(goal.startBodyFat) : null,
- startDate: goal.startDate,
- weeklyTarget: goal.weeklyTarget ? Number(goal.weeklyTarget) : null,
- status: goal.status,
- createdAt: goal.createdAt.getTime(),
- updatedAt: goal.updatedAt?.getTime() || goal.createdAt.getTime()
- };
- }
- }
|