feat(badges): 更新勋章系统,支持UUID作为勋章ID类型
feat(challenges): 优化进度报告,添加睡眠挑战勋章授予逻辑 fix(push-notifications): 修复推送测试服务初始化返回值问题
This commit is contained in:
@@ -473,38 +473,51 @@ export class ChallengesService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.winstonLogger.info('progress report updated', {
|
||||||
|
context: 'reportProgress',
|
||||||
|
userId,
|
||||||
|
challengeId,
|
||||||
|
reportDate,
|
||||||
|
reportedValue,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 🎖️ 检查是否为睡眠挑战且完成了第一次打卡,授予 goodSleep 勋章
|
||||||
|
if (challenge.type === ChallengeType.SLEEP) {
|
||||||
|
this.winstonLogger.info('检查是否为睡眠挑战且完成了第一次打卡,授予 goodSleep 勋章', {
|
||||||
|
context: 'reportProgress',
|
||||||
|
userId,
|
||||||
|
challengeId,
|
||||||
|
badgeCode: 'goodSleep',
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
await this.badgeService.awardBadge(userId, 'goodSleep', {
|
||||||
|
source: BadgeSource.CHALLENGE,
|
||||||
|
sourceId: challengeId,
|
||||||
|
metadata: {
|
||||||
|
challengeName: challenge.title,
|
||||||
|
challengeType: challenge.type,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.winstonLogger.info('授予睡眠挑战勋章成功', {
|
||||||
|
context: 'reportProgress',
|
||||||
|
userId,
|
||||||
|
challengeId,
|
||||||
|
badgeCode: 'goodSleep',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// 勋章授予失败不应影响主流程,仅记录日志
|
||||||
|
this.winstonLogger.error('授予睡眠挑战勋章失败', {
|
||||||
|
context: 'reportProgress',
|
||||||
|
userId,
|
||||||
|
challengeId,
|
||||||
|
error: error instanceof Error ? error.message : '未知错误',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (report.reportedValue >= reportCompletedValue && !dayjs(participant.lastProgressAt).isSame(dayjs(), 'd')) {
|
if (report.reportedValue >= reportCompletedValue && !dayjs(participant.lastProgressAt).isSame(dayjs(), 'd')) {
|
||||||
participant.progressValue++
|
participant.progressValue++
|
||||||
participant.lastProgressAt = now;
|
participant.lastProgressAt = now;
|
||||||
|
|
||||||
// 🎖️ 检查是否为睡眠挑战且完成了第一次打卡,授予 goodSleep 勋章
|
|
||||||
if (challenge.type === ChallengeType.SLEEP) {
|
|
||||||
try {
|
|
||||||
await this.badgeService.awardBadge(userId, 'goodSleep', {
|
|
||||||
source: BadgeSource.CHALLENGE,
|
|
||||||
sourceId: challengeId,
|
|
||||||
metadata: {
|
|
||||||
challengeName: challenge.title,
|
|
||||||
challengeType: challenge.type,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.winstonLogger.info('授予睡眠挑战勋章成功', {
|
|
||||||
context: 'reportProgress',
|
|
||||||
userId,
|
|
||||||
challengeId,
|
|
||||||
badgeCode: 'goodSleep',
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
// 勋章授予失败不应影响主流程,仅记录日志
|
|
||||||
this.winstonLogger.error('授予睡眠挑战勋章失败', {
|
|
||||||
context: 'reportProgress',
|
|
||||||
userId,
|
|
||||||
challengeId,
|
|
||||||
error: error instanceof Error ? error.message : '未知错误',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (participant.progressValue >= (participant.challenge?.minimumCheckInDays || 0) && participant.status !== ChallengeParticipantStatus.COMPLETED) {
|
if (participant.progressValue >= (participant.challenge?.minimumCheckInDays || 0) && participant.status !== ChallengeParticipantStatus.COMPLETED) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export class PushTestService implements OnModuleInit {
|
|||||||
async onModuleInit() {
|
async onModuleInit() {
|
||||||
// 检查是否启用推送测试
|
// 检查是否启用推送测试
|
||||||
const enablePushTest = this.configService.get<boolean>('ENABLE_PUSH_TEST', false);
|
const enablePushTest = this.configService.get<boolean>('ENABLE_PUSH_TEST', false);
|
||||||
|
return
|
||||||
if (!enablePushTest) {
|
if (!enablePushTest) {
|
||||||
this.logger.log('Push test is disabled. Skipping...');
|
this.logger.log('Push test is disabled. Skipping...');
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ export enum BadgeSource {
|
|||||||
})
|
})
|
||||||
export class UserBadge extends Model {
|
export class UserBadge extends Model {
|
||||||
@Column({
|
@Column({
|
||||||
type: DataType.INTEGER,
|
type: DataType.CHAR(36),
|
||||||
|
defaultValue: DataType.UUIDV4,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
autoIncrement: true,
|
|
||||||
})
|
})
|
||||||
declare id: number;
|
declare id: string;
|
||||||
|
|
||||||
@ForeignKey(() => User)
|
@ForeignKey(() => User)
|
||||||
@Column({
|
@Column({
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export class BadgeService {
|
|||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
async getUserBadges(userId: string): Promise<Array<{
|
async getUserBadges(userId: string): Promise<Array<{
|
||||||
id: number;
|
id: string;
|
||||||
code: string;
|
code: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user