实现完整的用户勋章功能模块: - 新增 BadgeConfig 和 UserBadge 数据模型,支持勋章配置和用户勋章管理 - 新增 BadgeService 服务,提供勋章授予、查询、展示状态管理等核心功能 - 在挑战服务中集成勋章授予逻辑,完成首次睡眠打卡授予 goodSleep 勋章,完成睡眠挑战授予 sleepChallengeMonth 勋章 - 新增用户勋章相关接口:获取用户勋章列表、获取可用勋章列表、标记勋章已展示 - 支持勋章分类(睡眠、运动、饮食等)、排序、启用状态管理 - 支持勋章来源追踪(挑战、系统、手动授予)和元数据记录
157 lines
4.2 KiB
TypeScript
157 lines
4.2 KiB
TypeScript
import { ApiProperty } from '@nestjs/swagger';
|
||
import { IsOptional, IsString, IsBoolean, IsDateString, IsNotEmpty } from 'class-validator';
|
||
import { BaseResponseDto } from '../../base.dto';
|
||
|
||
// 勋章基本信息
|
||
export class BadgeInfoDto {
|
||
@ApiProperty({ description: '勋章代码', example: 'goodSleep' })
|
||
code: string;
|
||
|
||
@ApiProperty({ description: '勋章名称', example: '好眠达人' })
|
||
name: string;
|
||
|
||
@ApiProperty({ description: '勋章描述', example: '完成首次睡眠挑战' })
|
||
description: string;
|
||
|
||
@ApiProperty({ description: '勋章图片URL' })
|
||
imageUrl: string;
|
||
|
||
@ApiProperty({ description: '勋章分类', example: 'sleep' })
|
||
category: string;
|
||
|
||
@ApiProperty({ description: '排序顺序', example: 1 })
|
||
sortOrder: number;
|
||
}
|
||
|
||
// 用户勋章信息
|
||
export class UserBadgeDto {
|
||
@ApiProperty({ description: '记录ID', example: 1 })
|
||
id: number;
|
||
|
||
@ApiProperty({ description: '勋章代码', example: 'goodSleep' })
|
||
code: string;
|
||
|
||
@ApiProperty({ description: '勋章名称', example: '好眠达人' })
|
||
name: string;
|
||
|
||
@ApiProperty({ description: '勋章描述', example: '完成首次睡眠挑战' })
|
||
description: string;
|
||
|
||
@ApiProperty({ description: '勋章图片URL' })
|
||
imageUrl: string;
|
||
|
||
@ApiProperty({ description: '勋章分类', example: 'sleep' })
|
||
category: string;
|
||
|
||
@ApiProperty({ description: '获得时间' })
|
||
awardedAt: Date;
|
||
|
||
@ApiProperty({ description: '授予来源', example: 'challenge' })
|
||
source: string;
|
||
|
||
@ApiProperty({ description: '来源ID(如挑战ID)', required: false })
|
||
sourceId?: string;
|
||
|
||
@ApiProperty({ description: '元数据', required: false })
|
||
metadata?: Record<string, any>;
|
||
|
||
@ApiProperty({ description: '是否已展示过', example: false })
|
||
isShow: boolean;
|
||
}
|
||
|
||
// 可用勋章信息(包含是否已获得)
|
||
export class AvailableBadgeDto extends BadgeInfoDto {
|
||
@ApiProperty({ description: '是否已获得', example: false })
|
||
isAwarded: boolean;
|
||
|
||
@ApiProperty({ description: '获得时间(如果已获得)', required: false })
|
||
awardedAt?: Date;
|
||
|
||
@ApiProperty({ description: '是否已展示过(如果已获得)', required: false })
|
||
isShow?: boolean;
|
||
}
|
||
|
||
// 获取用户勋章列表响应
|
||
export class GetUserBadgesResponseDto implements BaseResponseDto<{
|
||
badges: UserBadgeDto[];
|
||
total: number;
|
||
}> {
|
||
@ApiProperty({ description: '响应状态码', example: 0 })
|
||
code: number;
|
||
|
||
@ApiProperty({ description: '响应消息', example: 'success' })
|
||
message: string;
|
||
|
||
@ApiProperty({
|
||
description: '用户勋章数据',
|
||
example: {
|
||
badges: [
|
||
{
|
||
id: 1,
|
||
code: 'goodSleep',
|
||
name: '好眠达人',
|
||
description: '完成首次睡眠挑战',
|
||
imageUrl: 'https://example.com/badge.png',
|
||
category: 'sleep',
|
||
awardedAt: '2025-01-14T07:00:00Z',
|
||
source: 'challenge',
|
||
sourceId: 'challenge-uuid',
|
||
},
|
||
],
|
||
total: 1,
|
||
},
|
||
})
|
||
data: {
|
||
badges: UserBadgeDto[];
|
||
total: number;
|
||
};
|
||
}
|
||
|
||
// 获取所有可用勋章响应
|
||
export class GetAvailableBadgesResponseDto implements BaseResponseDto<AvailableBadgeDto[]> {
|
||
@ApiProperty({ description: '响应状态码', example: 0 })
|
||
code: number;
|
||
|
||
@ApiProperty({ description: '响应消息', example: 'success' })
|
||
message: string;
|
||
|
||
@ApiProperty({
|
||
description: '所有可用勋章列表',
|
||
example: [
|
||
{
|
||
code: 'goodSleep',
|
||
name: '好眠达人',
|
||
description: '完成首次睡眠挑战',
|
||
imageUrl: 'https://example.com/badge.png',
|
||
category: 'sleep',
|
||
sortOrder: 1,
|
||
isAwarded: true,
|
||
awardedAt: '2025-01-14T07:00:00Z',
|
||
},
|
||
],
|
||
})
|
||
data: AvailableBadgeDto[];
|
||
}
|
||
|
||
// 标记勋章已展示请求
|
||
export class MarkBadgeShownDto {
|
||
@ApiProperty({ description: '勋章代码', example: 'goodSleep' })
|
||
@IsString()
|
||
@IsNotEmpty()
|
||
badgeCode: string;
|
||
}
|
||
|
||
// 标记勋章已展示响应
|
||
export class MarkBadgeShownResponseDto implements BaseResponseDto<{ success: boolean }> {
|
||
@ApiProperty({ description: '响应状态码', example: 0 })
|
||
code: number;
|
||
|
||
@ApiProperty({ description: '响应消息', example: 'success' })
|
||
message: string;
|
||
|
||
@ApiProperty({
|
||
description: '操作结果',
|
||
example: { success: true },
|
||
})
|
||
data: { success: boolean };
|
||
} |