feat(challenges): 更新自定义挑战功能,支持时间戳转换及数据模型调整
This commit is contained in:
@@ -166,8 +166,8 @@ export class ChallengesService {
|
||||
requirementLabel: challenge.requirementLabel,
|
||||
status,
|
||||
unit: challenge.progressUnit,
|
||||
startAt: challenge.startAt,
|
||||
endAt: challenge.endAt,
|
||||
startAt: new Date(challenge.startAt).getTime(),
|
||||
endAt: new Date(challenge.endAt).getTime(),
|
||||
participantsCount: participantsCountMap.get(challenge.id) ?? 0,
|
||||
rankingDescription: challenge.rankingDescription,
|
||||
highlightTitle: challenge.highlightTitle,
|
||||
@@ -617,7 +617,7 @@ export class ChallengesService {
|
||||
}
|
||||
|
||||
|
||||
private computeStatus(startAt: number, endAt: number): ChallengeStatus {
|
||||
private computeStatus(startAt: Date | number, endAt: Date | number): ChallengeStatus {
|
||||
const now = dayjs();
|
||||
const start = dayjs(startAt);
|
||||
const end = dayjs(endAt);
|
||||
@@ -822,6 +822,15 @@ export class ChallengesService {
|
||||
throw new BadRequestException('结束时间必须晚于开始时间');
|
||||
}
|
||||
|
||||
// 将毫秒时间戳转换为 Date 对象,以匹配数据库 DATETIME 类型
|
||||
const startAtDate = new Date(dto.startAt);
|
||||
const endAtDate = new Date(dto.endAt);
|
||||
|
||||
// 验证日期是否有效
|
||||
if (isNaN(startAtDate.getTime()) || isNaN(endAtDate.getTime())) {
|
||||
throw new BadRequestException('无效的时间戳');
|
||||
}
|
||||
|
||||
// 检查创建频率限制(每天最多创建 5 个)
|
||||
const recentCount = await this.challengeModel.count({
|
||||
where: {
|
||||
@@ -839,13 +848,14 @@ export class ChallengesService {
|
||||
// 生成分享码
|
||||
const shareCode = await this.generateUniqueShareCode();
|
||||
|
||||
|
||||
// 创建挑战
|
||||
const challenge = await this.challengeModel.create({
|
||||
title: dto.title,
|
||||
type: dto.type,
|
||||
image: dto.image || null,
|
||||
startAt: dto.startAt,
|
||||
endAt: dto.endAt,
|
||||
startAt: startAtDate,
|
||||
endAt: endAtDate,
|
||||
periodLabel: dto.periodLabel || null,
|
||||
durationLabel: dto.durationLabel,
|
||||
requirementLabel: dto.requirementLabel,
|
||||
@@ -854,9 +864,9 @@ export class ChallengesService {
|
||||
progressUnit: dto.progressUnit || '天',
|
||||
minimumCheckInDays: dto.minimumCheckInDays,
|
||||
rankingDescription: dto.rankingDescription || '连续打卡榜',
|
||||
highlightTitle: dto.highlightTitle || '坚持挑战',
|
||||
highlightSubtitle: dto.highlightSubtitle || '养成好习惯',
|
||||
ctaLabel: dto.ctaLabel || '立即加入',
|
||||
highlightTitle: dto.title,
|
||||
highlightSubtitle: dto.summary || '养成好习惯',
|
||||
ctaLabel: '立即加入',
|
||||
source: ChallengeSource.CUSTOM,
|
||||
creatorId: userId,
|
||||
shareCode,
|
||||
@@ -865,7 +875,10 @@ export class ChallengesService {
|
||||
challengeState: ChallengeState.ACTIVE,
|
||||
});
|
||||
|
||||
this.winstonLogger.info('创建自定义挑战成功', {
|
||||
// 创建者自动加入挑战
|
||||
await this.joinChallenge(userId, challenge.id);
|
||||
|
||||
this.winstonLogger.info('创建自定义挑战成功,创建者已自动加入', {
|
||||
context: 'createCustomChallenge',
|
||||
userId,
|
||||
challengeId: challenge.id,
|
||||
@@ -1115,8 +1128,8 @@ export class ChallengesService {
|
||||
creatorId: challenge.creatorId,
|
||||
shareCode: challenge.shareCode,
|
||||
image: challenge.image,
|
||||
startAt: challenge.startAt,
|
||||
endAt: challenge.endAt,
|
||||
startAt: new Date(challenge.startAt).getTime(),
|
||||
endAt: new Date(challenge.endAt).getTime(),
|
||||
periodLabel: challenge.periodLabel,
|
||||
durationLabel: challenge.durationLabel,
|
||||
requirementLabel: challenge.requirementLabel,
|
||||
|
||||
@@ -77,23 +77,6 @@ export class CreateCustomChallengeDto {
|
||||
@MaxLength(255)
|
||||
rankingDescription?: string;
|
||||
|
||||
@ApiProperty({ description: '高亮标题', example: '坚持21天', required: false })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@MaxLength(255)
|
||||
highlightTitle?: string;
|
||||
|
||||
@ApiProperty({ description: '高亮副标题', example: '养成好习惯', required: false })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@MaxLength(255)
|
||||
highlightSubtitle?: string;
|
||||
|
||||
@ApiProperty({ description: 'CTA 按钮文字', example: '立即加入', required: false })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@MaxLength(128)
|
||||
ctaLabel?: string;
|
||||
|
||||
@ApiProperty({ description: '是否公开(可通过分享码加入)', default: true })
|
||||
@IsBoolean()
|
||||
|
||||
@@ -55,18 +55,18 @@ export class Challenge extends Model {
|
||||
declare image: string;
|
||||
|
||||
@Column({
|
||||
type: DataType.BIGINT,
|
||||
type: DataType.DATE,
|
||||
allowNull: false,
|
||||
comment: '挑战开始时间(时间戳)',
|
||||
comment: '挑战开始时间',
|
||||
})
|
||||
declare startAt: number;
|
||||
declare startAt: Date;
|
||||
|
||||
@Column({
|
||||
type: DataType.BIGINT,
|
||||
type: DataType.DATE,
|
||||
allowNull: false,
|
||||
comment: '挑战结束时间(时间戳)',
|
||||
comment: '挑战结束时间',
|
||||
})
|
||||
declare endAt: number;
|
||||
declare endAt: Date;
|
||||
|
||||
@Column({
|
||||
type: DataType.STRING(128),
|
||||
@@ -142,7 +142,7 @@ export class Challenge extends Model {
|
||||
|
||||
@Column({
|
||||
type: DataType.STRING(128),
|
||||
allowNull: false,
|
||||
allowNull: true,
|
||||
comment: 'CTA 按钮文字',
|
||||
})
|
||||
declare ctaLabel: string;
|
||||
|
||||
Reference in New Issue
Block a user