feat(badges): 添加用户勋章系统,支持睡眠挑战勋章自动授予

实现完整的用户勋章功能模块:
- 新增 BadgeConfig 和 UserBadge 数据模型,支持勋章配置和用户勋章管理
- 新增 BadgeService 服务,提供勋章授予、查询、展示状态管理等核心功能
- 在挑战服务中集成勋章授予逻辑,完成首次睡眠打卡授予 goodSleep 勋章,完成睡眠挑战授予 sleepChallengeMonth 勋章
- 新增用户勋章相关接口:获取用户勋章列表、获取可用勋章列表、标记勋章已展示
- 支持勋章分类(睡眠、运动、饮食等)、排序、启用状态管理
- 支持勋章来源追踪(挑战、系统、手动授予)和元数据记录
This commit is contained in:
richarjiang
2025-11-14 17:08:02 +08:00
parent f04c2ccd5d
commit 7b4d7c4459
8 changed files with 792 additions and 3 deletions

View File

@@ -41,6 +41,7 @@ import { UserActivityService } from './services/user-activity.service';
import { GetUserActivityHistoryResponseDto } from './dto/user-activity.dto';
import { ActivityActionType, ActivityEntityType } from '../activity-logs/models/activity-log.model';
import { BadgeService } from './services/badge.service';
@@ -74,6 +75,7 @@ export class UsersService {
private sequelize: Sequelize,
private readonly activityLogsService: ActivityLogsService,
private readonly userActivityService: UserActivityService,
private readonly badgeService: BadgeService,
) { }
async getProfile(user: AccessTokenPayload): Promise<UserResponseDto> {
@@ -2561,4 +2563,85 @@ export class UsersService {
return Math.floor(Date.now() / 1000) % 100000;
}
}
/**
* 获取用户勋章列表
*/
async getUserBadges(userId: string): Promise<any> {
try {
const badges = await this.badgeService.getUserBadges(userId);
const total = badges.length;
return {
code: ResponseCode.SUCCESS,
message: 'success',
data: {
badges,
total,
},
};
} catch (error) {
this.logger.error(`获取用户勋章列表失败: ${error instanceof Error ? error.message : '未知错误'}`);
return {
code: ResponseCode.ERROR,
message: `获取用户勋章列表失败: ${error instanceof Error ? error.message : '未知错误'}`,
data: {
badges: [],
total: 0,
},
};
}
}
/**
* 获取所有可用勋章(包含用户是否已获得)
*/
async getAvailableBadges(userId?: string): Promise<any> {
try {
const badges = await this.badgeService.getAvailableBadges(userId);
return {
code: ResponseCode.SUCCESS,
message: 'success',
data: badges,
};
} catch (error) {
this.logger.error(`获取可用勋章列表失败: ${error instanceof Error ? error.message : '未知错误'}`);
return {
code: ResponseCode.ERROR,
message: `获取可用勋章列表失败: ${error instanceof Error ? error.message : '未知错误'}`,
data: [],
};
}
}
/**
* 标记勋章已展示
*/
async markBadgeAsShown(userId: string, badgeCode: string): Promise<any> {
try {
const success = await this.badgeService.markBadgeAsShown(userId, badgeCode);
if (!success) {
return {
code: ResponseCode.ERROR,
message: '勋章不存在或标记失败',
data: { success: false },
};
}
return {
code: ResponseCode.SUCCESS,
message: 'success',
data: { success: true },
};
} catch (error) {
this.logger.error(`标记勋章已展示失败: ${error instanceof Error ? error.message : '未知错误'}`);
return {
code: ResponseCode.ERROR,
message: `标记勋章已展示失败: ${error instanceof Error ? error.message : '未知错误'}`,
data: { success: false },
};
}
}
}