- 新增挑战列表、详情、加入/退出、进度上报等 REST 接口 - 定义 Challenge / ChallengeParticipant 数据模型与状态枚举 - 提供排行榜查询与用户排名计算 - 包含接口文档与数据库初始化脚本
124 lines
2.6 KiB
TypeScript
124 lines
2.6 KiB
TypeScript
import { Table, Column, DataType, Model, HasMany } from 'sequelize-typescript';
|
||
import { ChallengeParticipant } from './challenge-participant.model';
|
||
|
||
export enum ChallengeStatus {
|
||
UPCOMING = 'upcoming',
|
||
ONGOING = 'ongoing',
|
||
EXPIRED = 'expired',
|
||
}
|
||
|
||
@Table({
|
||
tableName: 't_challenges',
|
||
underscored: true,
|
||
})
|
||
export class Challenge extends Model {
|
||
@Column({
|
||
type: DataType.CHAR(36),
|
||
defaultValue: DataType.UUIDV4,
|
||
primaryKey: true,
|
||
})
|
||
declare id: string;
|
||
|
||
@Column({
|
||
type: DataType.STRING(255),
|
||
allowNull: false,
|
||
comment: '挑战标题',
|
||
})
|
||
declare title: string;
|
||
|
||
@Column({
|
||
type: DataType.STRING(512),
|
||
allowNull: true,
|
||
comment: '挑战封面图',
|
||
})
|
||
declare image: string;
|
||
|
||
@Column({
|
||
type: DataType.DATE,
|
||
allowNull: false,
|
||
comment: '挑战开始时间',
|
||
})
|
||
declare startAt: Date;
|
||
|
||
@Column({
|
||
type: DataType.DATE,
|
||
allowNull: false,
|
||
comment: '挑战结束时间',
|
||
})
|
||
declare endAt: Date;
|
||
|
||
@Column({
|
||
type: DataType.STRING(128),
|
||
allowNull: true,
|
||
comment: '周期标签,例如「21天挑战」',
|
||
})
|
||
declare periodLabel: string | null;
|
||
|
||
@Column({
|
||
type: DataType.STRING(128),
|
||
allowNull: false,
|
||
comment: '持续时间标签,例如「持续21天」',
|
||
})
|
||
declare durationLabel: string;
|
||
|
||
@Column({
|
||
type: DataType.STRING(255),
|
||
allowNull: false,
|
||
comment: '挑战要求标签,例如「每日练习 1 次」',
|
||
})
|
||
declare requirementLabel: string;
|
||
|
||
@Column({
|
||
type: DataType.TEXT,
|
||
allowNull: true,
|
||
comment: '挑战概要说明',
|
||
})
|
||
declare summary: string | null;
|
||
|
||
@Column({
|
||
type: DataType.INTEGER,
|
||
allowNull: false,
|
||
comment: '挑战目标值(例如需要完成的天数)',
|
||
})
|
||
declare targetValue: number;
|
||
|
||
@Column({
|
||
type: DataType.STRING(64),
|
||
allowNull: false,
|
||
defaultValue: '天',
|
||
comment: '进度单位,用于展示排行榜指标',
|
||
})
|
||
declare progressUnit: string;
|
||
|
||
@Column({
|
||
type: DataType.STRING(255),
|
||
allowNull: true,
|
||
comment: '排行榜描述,例如「连续打卡榜」',
|
||
})
|
||
declare rankingDescription: string | null;
|
||
|
||
@Column({
|
||
type: DataType.STRING(255),
|
||
allowNull: false,
|
||
comment: '高亮标题',
|
||
})
|
||
declare highlightTitle: string;
|
||
|
||
@Column({
|
||
type: DataType.STRING(255),
|
||
allowNull: false,
|
||
comment: '高亮副标题',
|
||
})
|
||
declare highlightSubtitle: string;
|
||
|
||
@Column({
|
||
type: DataType.STRING(128),
|
||
allowNull: false,
|
||
comment: 'CTA 按钮文字',
|
||
})
|
||
declare ctaLabel: string;
|
||
|
||
@HasMany(() => ChallengeParticipant)
|
||
declare participants?: ChallengeParticipant[];
|
||
}
|