新增训练计划模块,包括控制器、服务、模型及数据传输对象,更新应用模块以引入新模块,同时在AI教练模块中添加体态评估功能,支持体重识别与更新,优化用户体重历史记录管理。

This commit is contained in:
richarjiang
2025-08-14 12:57:03 +08:00
parent 8c358a21f7
commit 24924e5d81
26 changed files with 935 additions and 5 deletions

View File

@@ -0,0 +1,29 @@
import { ApiProperty } from '@nestjs/swagger';
import { BaseResponseDto } from '../../base.dto';
export enum RecommendationType {
Article = 'article',
Checkin = 'checkin',
}
export class GetRecommendationsQueryDto {
@ApiProperty({ required: false, description: '数量默认10' })
limit?: number = 10;
}
export interface RecommendationCard {
id: string;
type: RecommendationType;
title?: string;
coverUrl?: string;
// 若为文章关联文章ID
articleId?: string;
// 若为打卡,提示信息
subtitle?: string;
// 其他扩展
extra?: Record<string, any>;
}
export type GetRecommendationsResponseDto = BaseResponseDto<RecommendationCard[]>;

View File

@@ -0,0 +1,21 @@
import { Controller, Get, HttpCode, HttpStatus, Query, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
import { GetRecommendationsQueryDto, GetRecommendationsResponseDto } from './dto/recommendation.dto';
import { RecommendationsService } from './recommendations.service';
@ApiTags('recommendations')
@Controller('recommendations')
@UseGuards(JwtAuthGuard)
export class RecommendationsController {
constructor(private readonly recommendationsService: RecommendationsService) { }
@Get('list')
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: '为你推荐列表' })
async list(@Query() query: GetRecommendationsQueryDto): Promise<GetRecommendationsResponseDto> {
return this.recommendationsService.list(query);
}
}

View File

@@ -0,0 +1,14 @@
import { Module } from '@nestjs/common';
import { RecommendationsService } from './recommendations.service';
import { RecommendationsController } from './recommendations.controller';
import { ArticlesModule } from '../articles/articles.module';
import { UsersModule } from '../users/users.module';
@Module({
imports: [ArticlesModule, UsersModule],
providers: [RecommendationsService],
controllers: [RecommendationsController],
})
export class RecommendationsModule { }

View File

@@ -0,0 +1,41 @@
import { Injectable, Logger } from '@nestjs/common';
import { ArticlesService } from '../articles/articles.service';
import { GetRecommendationsQueryDto, GetRecommendationsResponseDto, RecommendationCard, RecommendationType } from './dto/recommendation.dto';
import { ResponseCode } from '../base.dto';
import * as dayjs from 'dayjs';
@Injectable()
export class RecommendationsService {
private readonly logger = new Logger(RecommendationsService.name);
constructor(private readonly articlesService: ArticlesService) { }
// 为你推荐:混合文章与每日打卡卡片
async list(query: GetRecommendationsQueryDto): Promise<GetRecommendationsResponseDto> {
const limit = Math.min(50, Math.max(1, Number(query.limit || 10)));
// 取最新文章若干
const articlesRes = await this.articlesService.query({ page: 1, pageSize: limit } as any);
const articleCards: RecommendationCard[] = (articlesRes.data.list || []).map(a => ({
id: `article-${a.id}`,
type: RecommendationType.Article,
title: a.title,
articleId: a.id,
extra: { publishedDate: a.publishedDate, readCount: a.readCount },
}));
// 构造每日打卡卡片(今天)
const today = dayjs().format('YYYY-MM-DD');
const checkinCard: RecommendationCard = {
id: `checkin-${today}`,
type: RecommendationType.Checkin,
title: '今日打卡',
subtitle: '完成一次普拉提训练,记录你的坚持',
extra: { date: today },
};
const cards = [checkinCard, ...articleCards].slice(0, limit);
return { code: ResponseCode.SUCCESS, message: 'success', data: cards };
}
}