返回 AiToEarn
task.service.ts
根目录 / project / aitoearn-electron / server / src / modules / task / task.service.ts
1 /*
2 * @Author: nevin
3 * @Date: 2025-02-18 22:32:02
4 * @LastEditTime: 2025-02-27 22:43:33
5 * @LastEditors: nevin
6 * @Description: 用户端任务
7 */
8 import { Injectable, NotFoundException } from '@nestjs/common';
9 import { InjectModel } from '@nestjs/mongoose';
10 import { Model, Types } from 'mongoose';
11 import { Task, TaskStatus } from '../../db/schema/task.schema';
12 import { UserTask, UserTaskStatus } from '../../db/schema/user-task.schema';
13 import { QueryTaskDto } from './dto/query-task.dto';
14 import { createPaginationObject } from 'src/common/paginate/create-pagination';
15 import { ObjectId } from 'mongodb';
16 import { TaskMaterial } from 'src/db/schema/taskMaterial.schema';
17
18 @Injectable()
19 export class TaskService {
20 constructor(
21 @InjectModel(Task.name) private taskModel: Model<Task>,
22 @InjectModel(UserTask.name) private userTaskModel: Model<UserTask>,
23 @InjectModel(TaskMaterial.name)
24 private taskMaterialModel: Model<TaskMaterial>,
25 ) {}
26
27 /**
28 * 获取任务列表
29 * @param query
30 * @returns
31 */
32 async findAll(userId: string, query: QueryTaskDto) {
33 const {
34 page = 1,
35 pageSize = 10,
36 type,
37 keyword,
38 productLevel,
39 requiresShoppingCart,
40 } = query;
41 const filter: any = {
42 status: TaskStatus.ACTIVE,
43 };
44
45 if (type) filter.type = type;
46 if (productLevel) filter.productLevel = productLevel;
47 if (requiresShoppingCart !== undefined)
48 filter.requiresShoppingCart = requiresShoppingCart;
49 if (keyword) filter.title = new RegExp(keyword, 'i');
50
51 const listP = this.taskModel.aggregate([
52 {
53 $match: {
54 ...filter,
55 },
56 },
57 {
58 $lookup: {
59 from: 'user_task', // 连接 user_task 表
60 let: { task_id: '$_id' }, // 定义变量 task_id 为当前任务的 _id
61 pipeline: [
62 {
63 $match: {
64 $expr: {
65 $and: [
66 { $eq: ['$taskId', '$$task_id'] }, // 匹配 taskId
67 { $eq: ['$userId', new Types.ObjectId(userId)] }, // 匹配 userId
68 ],
69 },
70 },
71 },
72 ],
73 as: 'accepted_info', // 将匹配的结果存放到 user_tasks 字段中
74 },
75 },
76 {
77 $addFields: {
78 isAccepted: {
79 $cond: {
80 if: { $gt: [{ $size: '$accepted_info' }, 0] }, // 如果 accepted_info 数组不为空
81 then: true, // 则 is_accepted 为 true
82 else: false, // 否则为 false
83 },
84 },
85 },
86 },
87 {
88 $project: {
89 accepted_info: 0, // 移除 accepted_info 字段(可选)
90 },
91 },
92 { $skip: (page - 1) * pageSize }, // 跳过前面的记录
93 { $limit: pageSize }, // 限制每页的记录数量
94 ]);
95
96 const totaP = this.taskModel.countDocuments(filter);
97 const [items, total] = await Promise.all([listP, totaP]);
98
99 return createPaginationObject<Task>({
100 items,
101 totalItems: total,
102 currentPage: page,
103 limit: pageSize,
104 });
105 }
106
107 async findOne(id: string): Promise<Task> {
108 const task = await this.taskModel.findById(id).exec();
109 if (!task) {
110 throw new NotFoundException('Task not found');
111 }
112 return task;
113 }
114
115 // 统计合计进行中的任务的金额总数
116 async getTotalAmountOfDoingTasks(userId: string): Promise<number> {
117 const tasks = await this.userTaskModel.find({
118 status: UserTaskStatus.APPROVED,
119 userId: new ObjectId(userId),
120 });
121
122 let totalAmount = 0;
123
124 for (const task of tasks) totalAmount += task.reward;
125 return totalAmount;
126 }
127
128 // 根据ID获取素材
129 async getTaskMaterialById(taskMaterialId: string): Promise<TaskMaterial> {
130 const materials = await this.taskMaterialModel.findById(taskMaterialId);
131 return materials;
132 }
133
134 /**
135 * 获取最优素材
136 * @param taskId
137 * @returns
138 */
139 async getFristTaskMaterial(taskId: string) {
140 const res = await this.taskMaterialModel
141 .findOne({
142 taskId: new ObjectId(taskId),
143 })
144 .sort({ usedCount: 1 });
145
146 return res;
147 }
148
149 // 素材使用次数+1
150 async upTaskMaterialUsedCount(taskMaterialId: string): Promise<boolean> {
151 try {
152 const res = await this.taskMaterialModel.updateOne(
153 { _id: new ObjectId(taskMaterialId) },
154 { $inc: { usedCount: 1 } },
155 );
156
157 return res.modifiedCount > 0;
158 } catch (error) {
159 console.log(
160 '----------- upTaskMaterialUsedCount error -----------',
161 error,
162 );
163
164 return false;
165 }
166 }
167 }
168
168 lines TYPESCRIPT