| 1 | /* |
| 2 | * @Author: nevin |
| 3 | * @Date: 2025-02-18 22:32:02 |
| 4 | * @LastEditTime: 2025-03-04 15:23:22 |
| 5 | * @LastEditors: nevin |
| 6 | * @Description: 任务 |
| 7 | */ |
| 8 | import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; |
| 9 | import { TimeTemp } from './time.tamp'; |
| 10 | import { AccountType } from './account.schema'; |
| 11 | |
| 12 | export enum TaskType { |
| 13 | PRODUCT = 'product', // 商品任务 |
| 14 | VIDEO = 'video', // 视频任务 |
| 15 | ARTICLE = 'article', // 文章任务 |
| 16 | PROMOTION = 'promotion', // 拉新任务 |
| 17 | INTERACTION = 'interaction', // 互动任务 |
| 18 | } |
| 19 | |
| 20 | export enum TaskStatus { |
| 21 | ACTIVE = 'active', // 进行中 |
| 22 | CANCELLED = 'cancelled', // 已取消 |
| 23 | DEL = 'del', // 已删除 |
| 24 | } |
| 25 | |
| 26 | export interface TaskFile { |
| 27 | name: string; |
| 28 | url: string; |
| 29 | } |
| 30 | |
| 31 | export class TaskFileSchema implements TaskFile { |
| 32 | @Prop({ |
| 33 | required: true, |
| 34 | comment: '指标名称', |
| 35 | }) |
| 36 | name: string; |
| 37 | |
| 38 | @Prop({ |
| 39 | required: true, |
| 40 | comment: '指标值', |
| 41 | }) |
| 42 | url: string; |
| 43 | } |
| 44 | |
| 45 | @Schema({ toJSON: { virtuals: true }, toObject: { virtuals: true } }) |
| 46 | export class TaskData { |
| 47 | @Prop({ required: false }) |
| 48 | title?: string; |
| 49 | |
| 50 | @Prop({ required: false }) |
| 51 | desc?: string; |
| 52 | } |
| 53 | // 视频 |
| 54 | @Schema({ |
| 55 | toJSON: { virtuals: true }, |
| 56 | toObject: { virtuals: true }, |
| 57 | }) |
| 58 | export class TaskVideo extends TaskData { |
| 59 | @Prop({ required: false }) |
| 60 | coverUrl?: string; // 封面图 |
| 61 | |
| 62 | @Prop({ required: true }) |
| 63 | videoUrl: string; |
| 64 | |
| 65 | @Prop({ required: false, type: [String], default: [] }) |
| 66 | topicList: string[]; |
| 67 | } |
| 68 | |
| 69 | // 文章 |
| 70 | @Schema({ |
| 71 | toJSON: { virtuals: true }, |
| 72 | toObject: { virtuals: true }, |
| 73 | }) |
| 74 | export class TaskArticleImg { |
| 75 | @Prop({ required: true, default: '' }) |
| 76 | content: string; // 内容 |
| 77 | |
| 78 | @Prop({ required: true }) |
| 79 | imageUrl: string; |
| 80 | } |
| 81 | @Schema({ |
| 82 | toJSON: { virtuals: true }, |
| 83 | toObject: { virtuals: true }, |
| 84 | }) |
| 85 | export class TaskArticleMaterial { |
| 86 | @Prop({ required: false }) |
| 87 | coverUrl?: string; // 封面图 |
| 88 | |
| 89 | @Prop({ required: false }) |
| 90 | title?: string; // 标题 |
| 91 | |
| 92 | @Prop({ required: true }) |
| 93 | temp: string; // 模板字符 |
| 94 | |
| 95 | // 图片列表 |
| 96 | @Prop({ required: true, type: [TaskArticleImg], default: [] }) |
| 97 | imageList: TaskArticleImg[]; |
| 98 | } |
| 99 | |
| 100 | @Schema({ |
| 101 | toJSON: { virtuals: true }, |
| 102 | toObject: { virtuals: true }, |
| 103 | }) |
| 104 | export class TaskArticle extends TaskData { |
| 105 | @Prop({ required: true, type: [TaskArticleMaterial], default: [] }) |
| 106 | materialList: TaskArticleMaterial[]; // 素材列表 |
| 107 | |
| 108 | @Prop({ required: false, type: [String], default: [] }) |
| 109 | topicList: string[]; |
| 110 | |
| 111 | // 图片列表 |
| 112 | @Prop({ required: true, type: [String], default: [] }) |
| 113 | imageList: string[]; |
| 114 | } |
| 115 | |
| 116 | // 推广 |
| 117 | @Schema({ |
| 118 | toJSON: { virtuals: true }, |
| 119 | toObject: { virtuals: true }, |
| 120 | }) |
| 121 | export class TaskPromotion extends TaskData {} |
| 122 | |
| 123 | // 商品 |
| 124 | @Schema({ |
| 125 | toJSON: { virtuals: true }, |
| 126 | toObject: { virtuals: true }, |
| 127 | }) |
| 128 | export class TaskProduct extends TaskData { |
| 129 | @Prop({ required: true }) // 商品价格 |
| 130 | price: number; |
| 131 | |
| 132 | // 销量 |
| 133 | @Prop({ required: false }) |
| 134 | sales?: number; |
| 135 | } |
| 136 | |
| 137 | // 互动 |
| 138 | @Schema({ |
| 139 | toJSON: { virtuals: true }, |
| 140 | toObject: { virtuals: true }, |
| 141 | }) |
| 142 | export class TaskInteraction extends TaskData { |
| 143 | @Prop({ required: true, enum: AccountType }) |
| 144 | accountType: AccountType; // 平台类型 |
| 145 | |
| 146 | @Prop({ required: true, type: String }) |
| 147 | worksId: string; // 作品ID |
| 148 | |
| 149 | @Prop({ required: false, type: String }) |
| 150 | authorId?: string; // 作者ID |
| 151 | |
| 152 | @Prop({ required: false, type: String }) |
| 153 | commentContent?: string; // 评论内容,不填则使用AI |
| 154 | } |
| 155 | |
| 156 | @Schema({ |
| 157 | collection: 'task', |
| 158 | versionKey: false, |
| 159 | toJSON: { virtuals: true }, |
| 160 | toObject: { virtuals: true }, |
| 161 | timestamps: false, |
| 162 | }) |
| 163 | export class Task extends TimeTemp { |
| 164 | id: string; |
| 165 | |
| 166 | @Prop({ required: true }) |
| 167 | title: string; |
| 168 | |
| 169 | @Prop({ |
| 170 | required: true, |
| 171 | }) |
| 172 | description: string; // md文档 |
| 173 | |
| 174 | @Prop({ required: true, enum: TaskType }) |
| 175 | type: TaskType; |
| 176 | |
| 177 | @Prop({ |
| 178 | required: false, |
| 179 | }) |
| 180 | imageUrl: string; // 配图 |
| 181 | |
| 182 | @Prop({ type: Object, required: false }) |
| 183 | dataInfo: |
| 184 | | TaskVideo |
| 185 | | TaskPromotion |
| 186 | | TaskProduct |
| 187 | | TaskInteraction |
| 188 | | TaskArticle; |
| 189 | |
| 190 | @Prop({ type: [TaskFileSchema], default: [] }) |
| 191 | fileList: TaskFileSchema[]; // 附件地址列表 |
| 192 | |
| 193 | @Prop({ required: true, default: 0 }) |
| 194 | keepTime: number; // 保持时间(秒) |
| 195 | |
| 196 | @Prop({ default: false }) |
| 197 | requiresShoppingCart: boolean; // 是否需要挂购物车 |
| 198 | |
| 199 | @Prop({ required: true }) |
| 200 | maxRecruits: number; // 最大招募人数 |
| 201 | |
| 202 | @Prop({ default: 0 }) |
| 203 | currentRecruits: number; // 当前招募人数 |
| 204 | |
| 205 | @Prop({ required: true }) |
| 206 | deadline: Date; // 任务截止时间 |
| 207 | |
| 208 | @Prop({ required: true, type: Number }) |
| 209 | reward: number; // 任务奖励金额 |
| 210 | |
| 211 | @Prop({ default: TaskStatus.CANCELLED, enum: TaskStatus }) |
| 212 | status: TaskStatus; |
| 213 | |
| 214 | @Prop({ type: Array<AccountType>, required: true }) |
| 215 | accountTypes: AccountType[]; // 支持的平台tag列表 |
| 216 | } |
| 217 | |
| 218 | export const TaskSchema = SchemaFactory.createForClass(Task); |
| 219 |