返回 AiToEarn
user.service.ts
根目录 / project / aitoearn-electron / server / src / user / user.service.ts
1 /*
2 * @Author: nevin
3 * @Date: 2024-06-17 19:19:15
4 * @LastEditTime: 2025-03-03 14:05:25
5 * @LastEditors: nevin
6 * @Description:
7 */
8 import { Injectable } from '@nestjs/common';
9 import { InjectModel } from '@nestjs/mongoose';
10 import { Model } from 'mongoose';
11 import { User, UserStatus } from '../db/schema/user.schema';
12 import { RedisService } from '../lib/redis/redis.service';
13 import { QueryUserListDto } from './dto/user-admin.dto';
14 import { paginateModel } from '../common/paginate/create-pagination';
15 import { UserWallet } from 'src/db/schema/userWallet.shema';
16 import * as crypto from 'node:crypto';
17 import { RealAuthService } from './realAuth.service';
18
19 @Injectable()
20 export class UserService {
21 constructor(
22 private readonly redisService: RedisService,
23 private readonly realAuthService: RealAuthService,
24
25 @InjectModel(User.name)
26 private readonly userModel: Model<User>,
27
28 @InjectModel(UserWallet.name)
29 private readonly userWalletModel: Model<UserWallet>,
30 ) {}
31
32 async getUserInfoById(id: string) {
33 const key = `UserInfo:${id}`;
34 let userInfo: User = await this.redisService.get(key);
35 if (!!userInfo) return userInfo;
36
37 userInfo = await this.userModel.findById(id);
38 this.redisService.setKey(key, userInfo);
39 return userInfo;
40 }
41
42 async getUserInfoByPhone(phone: string) {
43 const userInfo: User = await this.userModel.findOne({
44 phone,
45 status: UserStatus.OPEN,
46 });
47 return userInfo;
48 }
49
50 async getUserInfoByMail(mail: string) {
51 const userInfo: User = await this.userModel.findOne({
52 mail,
53 status: UserStatus.OPEN,
54 });
55 return userInfo;
56 }
57
58 async getUserInfoByWxOpenId(wxOpenId: string) {
59 const userInfo: User = await this.userModel.findOne({
60 wxOpenid: wxOpenId,
61 status: UserStatus.OPEN,
62 });
63 return userInfo;
64 }
65
66 /**
67 * 创建用户
68 * @param newData
69 * @returns
70 */
71 async createUser(newData: User): Promise<User> {
72 const res = await this.userModel.create(newData);
73 return res;
74 }
75
76 // 更新
77 async updateUser(id: string, newData: User): Promise<User> {
78 const res = await this.userModel.findByIdAndUpdate(id, newData);
79 this.redisService.del(`UserInfo:${id}`);
80 return res;
81 }
82
83 // 更新密码
84 async updateUserPassword(
85 id: string,
86 newData: {
87 password: string;
88 salt: string;
89 },
90 ): Promise<0 | 1> {
91 const res = await this.userModel.updateOne(
92 { _id: id },
93 {
94 $set: {
95 password: newData.password,
96 salt: newData.salt,
97 },
98 },
99 );
100
101 this.redisService.del(`UserInfo:${id}`);
102 return res.modifiedCount > 0 ? 1 : 0;
103 }
104
105 // 用户注销
106 async deleteUser(userInfo: User): Promise<0 | 1> {
107 const res = await this.userModel.updateOne(
108 {
109 _id: userInfo.id,
110 },
111 {
112 $set: {
113 status: UserStatus.DELETE,
114 wxOpenid: '',
115 wxUnionid: '',
116 phone: '',
117 backData: {
118 wxOpenid: userInfo.wxOpenid,
119 wxUnionid: userInfo.wxUnionid,
120 phone: userInfo.phone,
121 },
122 },
123 },
124 );
125 this.redisService.del(`UserInfo:${userInfo.id}`);
126 return res.modifiedCount > 0 ? 1 : 0;
127 }
128
129 private getUserWalletInfo(userId: string) {
130 return this.userWalletModel.findOne({ userId });
131 }
132
133 /**
134 * 获取用户列表
135 */
136 async getUserList(query: QueryUserListDto) {
137 const { name, phone, status, field, order } = query;
138
139 const filter: any = {};
140 if (name) filter.name = new RegExp(name, 'i');
141 if (phone) filter.phone = new RegExp(phone, 'i');
142 if (status !== undefined) filter.status = status;
143
144 const sort: any = {};
145 if (field) {
146 sort[field] = order === 'DESC' ? -1 : 1;
147 } else {
148 sort.createdAt = -1; // 默认按创建时间倒序
149 }
150
151 const res = await paginateModel(
152 this.userModel,
153 query,
154 filter,
155 undefined, // populate options
156 sort,
157 );
158
159 const items = [];
160
161 for (const element of res.items) {
162 const walletInfo = await this.getUserWalletInfo(element.id);
163 const realAuthInfo = await this.realAuthService.getRealAuthModelByUserId(
164 element.id,
165 );
166
167 items.push({
168 id: element.id,
169 name: element.name,
170 phone: element.phone,
171 status: element.status,
172 createTime: element.createTime,
173 updateTime: element.updateTime,
174 wxOpenid: element.wxOpenid,
175 wxUnionid: element.wxUnionid,
176 balance: walletInfo?.balance || 0,
177 identifyNum: realAuthInfo?.identifyNum || '',
178 realName: realAuthInfo?.userName || '',
179 });
180 }
181
182 return {
183 items,
184 meta: res.meta,
185 };
186 }
187
188 /**
189 * 更新用户状态
190 */
191 async updateUserStatus(id: string, status: UserStatus): Promise<User> {
192 const res = await this.userModel.findByIdAndUpdate(
193 id,
194 { status },
195 { new: true },
196 );
197 this.redisService.del(`UserInfo:${id}`);
198 return res;
199 }
200
201 // 更新用户的电话号码
202 async updateUserPhone(id: string, phone: string): Promise<boolean> {
203 const res = await this.userModel.updateOne(
204 { _id: id },
205 { $set: { phone } },
206 );
207 this.redisService.del(`UserInfo:${id}`);
208 return res.modifiedCount > 0;
209 }
210
211 // 获取用户总数
212 async getUserCount() {
213 const count = await this.userModel.countDocuments();
214 return count;
215 }
216
217 /**
218 * 更新微信openID
219 */
220 async updateUserWxOpenId(id: string, openId: string): Promise<User> {
221 const res = await this.userModel.findByIdAndUpdate(
222 id,
223 { wxOpenid: openId },
224 { new: false },
225 );
226 this.redisService.del(`UserInfo:${id}`);
227 return res;
228 }
229
230 /**
231 * 生成推广码
232 * @param userId
233 * @param phone
234 * @returns
235 */
236 async generateUsePopularizeCode(userId: string, phone: string) {
237 // 先对手机号进行哈希处理
238 const phoneHash = crypto
239 .createHash('sha256')
240 .update(phone)
241 .digest('hex')
242 .substring(0, 16);
243
244 const combinedSalt = 'aitoearn' + phoneHash;
245
246 const hash = crypto
247 .createHash('sha256')
248 .update(userId)
249 .update(combinedSalt)
250 .digest('hex');
251
252 // 取部分哈希值转换为5位代码
253 const numericValue = parseInt(hash.substring(0, 6), 16);
254 const code = numericValue
255 .toString(36)
256 .slice(-5)
257 .toUpperCase()
258 .padStart(5, '0');
259
260 // 更新用户的推广码
261 await this.userModel.updateOne(
262 { _id: userId },
263 { $set: { popularizeCode: code } },
264 );
265 this.redisService.del(`UserInfo:${userId}`);
266
267 return code;
268 }
269
270 /**
271 * 根据推广码获取用户信息
272 * @param popularizeCode
273 * @returns
274 */
275 async getUserByPopularizeCode(popularizeCode: string): Promise<User> {
276 const userInfo: User = await this.userModel.findOne({
277 popularizeCode,
278 status: UserStatus.OPEN,
279 });
280 return userInfo;
281 }
282 }
283
283 lines TYPESCRIPT