/** * 用户服务类 * * 功能描述: * - 提供用户的增删改查操作 * - 处理用户数据的业务逻辑 * - 数据验证和错误处理 * * @author moyin * @version 1.0.0 * @since 2025-12-17 */ import { Injectable, ConflictException, NotFoundException, BadRequestException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, FindOptionsWhere } from 'typeorm'; import { Users } from './users.entity'; import { CreateUserDto } from './users.dto'; import { UserStatus } from '../../../business/user-mgmt/enums/user-status.enum'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; @Injectable() export class UsersService { constructor( @InjectRepository(Users) private readonly usersRepository: Repository, ) {} /** * 创建新用户 * * @param createUserDto 创建用户的数据传输对象 * @returns 创建的用户实体 * @throws BadRequestException 当数据验证失败时 */ async create(createUserDto: CreateUserDto): Promise { // 验证DTO const dto = plainToClass(CreateUserDto, createUserDto); const validationErrors = await validate(dto); if (validationErrors.length > 0) { const errorMessages = validationErrors.map(error => Object.values(error.constraints || {}).join(', ') ).join('; '); throw new BadRequestException(`数据验证失败: ${errorMessages}`); } // 创建用户实体 const user = new Users(); user.username = createUserDto.username; user.email = createUserDto.email || null; user.phone = createUserDto.phone || null; user.password_hash = createUserDto.password_hash || null; user.nickname = createUserDto.nickname; user.github_id = createUserDto.github_id || null; user.avatar_url = createUserDto.avatar_url || null; user.role = createUserDto.role || 1; user.email_verified = createUserDto.email_verified || false; user.status = createUserDto.status || UserStatus.ACTIVE; // 保存到数据库 return await this.usersRepository.save(user); } /** * 创建新用户(带重复检查) * * @param createUserDto 创建用户的数据传输对象 * @returns 创建的用户实体 * @throws ConflictException 当用户名、邮箱或手机号已存在时 * @throws BadRequestException 当数据验证失败时 */ async createWithDuplicateCheck(createUserDto: CreateUserDto): Promise { // 检查用户名是否已存在 if (createUserDto.username) { const existingUser = await this.usersRepository.findOne({ where: { username: createUserDto.username } }); if (existingUser) { throw new ConflictException('用户名已存在'); } } // 检查邮箱是否已存在 if (createUserDto.email) { const existingEmail = await this.usersRepository.findOne({ where: { email: createUserDto.email } }); if (existingEmail) { throw new ConflictException('邮箱已存在'); } } // 检查手机号是否已存在 if (createUserDto.phone) { const existingPhone = await this.usersRepository.findOne({ where: { phone: createUserDto.phone } }); if (existingPhone) { throw new ConflictException('手机号已存在'); } } // 检查GitHub ID是否已存在 if (createUserDto.github_id) { const existingGithub = await this.usersRepository.findOne({ where: { github_id: createUserDto.github_id } }); if (existingGithub) { throw new ConflictException('GitHub ID已存在'); } } // 调用普通的创建方法 return await this.create(createUserDto); } /** * 查询所有用户 * * @param limit 限制返回数量,默认100 * @param offset 偏移量,默认0 * @returns 用户列表 */ async findAll(limit: number = 100, offset: number = 0): Promise { return await this.usersRepository.find({ take: limit, skip: offset, order: { created_at: 'DESC' } }); } /** * 根据ID查询用户 * * @param id 用户ID * @returns 用户实体 * @throws NotFoundException 当用户不存在时 */ async findOne(id: bigint): Promise { const user = await this.usersRepository.findOne({ where: { id } }); if (!user) { throw new NotFoundException(`ID为 ${id} 的用户不存在`); } return user; } /** * 根据用户名查询用户 * * @param username 用户名 * @returns 用户实体或null */ async findByUsername(username: string): Promise { return await this.usersRepository.findOne({ where: { username } }); } /** * 根据邮箱查询用户 * * @param email 邮箱 * @returns 用户实体或null */ async findByEmail(email: string): Promise { return await this.usersRepository.findOne({ where: { email } }); } /** * 根据GitHub ID查询用户 * * @param githubId GitHub ID * @returns 用户实体或null */ async findByGithubId(githubId: string): Promise { return await this.usersRepository.findOne({ where: { github_id: githubId } }); } /** * 更新用户信息 * * @param id 用户ID * @param updateData 更新的数据 * @returns 更新后的用户实体 * @throws NotFoundException 当用户不存在时 * @throws ConflictException 当更新的数据与其他用户冲突时 */ async update(id: bigint, updateData: Partial): Promise { // 检查用户是否存在 const existingUser = await this.findOne(id); // 检查更新数据的唯一性约束 if (updateData.username && updateData.username !== existingUser.username) { const usernameExists = await this.usersRepository.findOne({ where: { username: updateData.username } }); if (usernameExists) { throw new ConflictException('用户名已存在'); } } if (updateData.email && updateData.email !== existingUser.email) { const emailExists = await this.usersRepository.findOne({ where: { email: updateData.email } }); if (emailExists) { throw new ConflictException('邮箱已存在'); } } if (updateData.phone && updateData.phone !== existingUser.phone) { const phoneExists = await this.usersRepository.findOne({ where: { phone: updateData.phone } }); if (phoneExists) { throw new ConflictException('手机号已存在'); } } if (updateData.github_id && updateData.github_id !== existingUser.github_id) { const githubExists = await this.usersRepository.findOne({ where: { github_id: updateData.github_id } }); if (githubExists) { throw new ConflictException('GitHub ID已存在'); } } // 更新用户数据 Object.assign(existingUser, updateData); return await this.usersRepository.save(existingUser); } /** * 删除用户 * * @param id 用户ID * @returns 删除操作结果 * @throws NotFoundException 当用户不存在时 */ async remove(id: bigint): Promise<{ affected: number; message: string }> { // 检查用户是否存在 await this.findOne(id); // 执行删除 - 使用where条件来处理bigint类型 const result = await this.usersRepository.delete({ id }); return { affected: result.affected || 0, message: `成功删除ID为 ${id} 的用户` }; } /** * 软删除用户(如果需要保留数据) * 注意:需要在实体中添加 @DeleteDateColumn 装饰器 * * @param id 用户ID * @returns 软删除操作结果 */ async softRemove(id: bigint): Promise { const user = await this.findOne(id); return await this.usersRepository.softRemove(user); } /** * 统计用户数量 * * @param conditions 查询条件 * @returns 用户数量 */ async count(conditions?: FindOptionsWhere): Promise { return await this.usersRepository.count({ where: conditions }); } /** * 检查用户是否存在 * * @param id 用户ID * @returns 是否存在 */ async exists(id: bigint): Promise { const count = await this.usersRepository.count({ where: { id } }); return count > 0; } /** * 批量创建用户 * * @param createUserDtos 用户数据数组 * @returns 创建的用户列表 */ async createBatch(createUserDtos: CreateUserDto[]): Promise { const users: Users[] = []; for (const dto of createUserDtos) { const user = await this.create(dto); users.push(user); } return users; } /** * 根据角色查询用户 * * @param role 角色值 * @returns 用户列表 */ async findByRole(role: number): Promise { return await this.usersRepository.find({ where: { role }, order: { created_at: 'DESC' } }); } /** * 搜索用户(根据用户名或昵称) * * @param keyword 搜索关键词 * @param limit 限制数量 * @returns 用户列表 */ async search(keyword: string, limit: number = 20): Promise { return await this.usersRepository .createQueryBuilder('user') .where('user.username LIKE :keyword OR user.nickname LIKE :keyword', { keyword: `%${keyword}%` }) .orderBy('user.created_at', 'DESC') .limit(limit) .getMany(); } }