import { Injectable, NotFoundException, ConflictException, BadRequestException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import * as bcrypt from 'bcrypt'; import { User } from './user.entity'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { QueryUserDto } from './dto/query-user.dto'; import { ChangePasswordDto } from './dto/change-password.dto'; @Injectable() export class UserService { constructor( @InjectRepository(User) private readonly userRepository: Repository, ) {} /** * 注册用户 */ async create(createUserDto: CreateUserDto): Promise { // 检查用户名是否已存在 const existingByUsername = await this.userRepository.findOne({ where: { username: createUserDto.username }, }); if (existingByUsername) { throw new ConflictException( `用户名 "${createUserDto.username}" 已存在`, ); } // 检查邮箱是否已存在 const existingByEmail = await this.userRepository.findOne({ where: { email: createUserDto.email }, }); if (existingByEmail) { throw new ConflictException(`邮箱 "${createUserDto.email}" 已存在`); } // 检查 phone 是否已存在(如果提供了) /* if (createUserDto.phone) { const existingByPhone = await this.userRepository.findOne({ where: { phone: createUserDto.phone }, }); if (existingByPhone) { throw new ConflictException( `Phone "${createUserDto.phone}" already exists`, ); } } // 检查 openId 是否已存在(如果提供了) if (createUserDto.openId) { const existingByOpenId = await this.userRepository.findOne({ where: { openId: createUserDto.openId }, }); if (existingByOpenId) { throw new ConflictException( `OpenId "${createUserDto.openId}" already exists`, ); } } // 检查 unionId 是否已存在(如果提供了) if (createUserDto.unionId) { const existingByUnionId = await this.userRepository.findOne({ where: { unionId: createUserDto.unionId }, }); if (existingByUnionId) { throw new ConflictException( `UnionId "${createUserDto.unionId}" already exists`, ); } } */ // 使用 bcrypt 加密密码 const saltRounds = 10; const passwordHash = await bcrypt.hash( createUserDto.password, saltRounds, ); // 创建用户 const user = this.userRepository.create({ username: createUserDto.username, passwordHash, email: createUserDto.email, nickname: createUserDto.nickname, avatarUrl: createUserDto.avatarUrl, phone: createUserDto.phone, openId: createUserDto.openId, unionId: createUserDto.unionId, status: 'active', role: createUserDto.role || 'user', // 默认为普通用户 }); return this.userRepository.save(user); } /** * 查询所有用户 */ async findAll(): Promise { return this.userRepository.find({ order: { createdAt: 'DESC', }, }); } /** * 根据 username 或 email 查询单个用户 */ async findOne(queryDto: QueryUserDto): Promise { if (!queryDto.username && !queryDto.email) { throw new BadRequestException('必须提供用户名或邮箱'); } const where: { username?: string; email?: string } = {}; if (queryDto.username) { where.username = queryDto.username; } if (queryDto.email) { where.email = queryDto.email; } const user = await this.userRepository.findOne({ where }); if (!user) { const identifier = queryDto.username || queryDto.email; throw new NotFoundException( `未找到${queryDto.username ? '用户名' : '邮箱'}为 "${identifier}" 的用户`, ); } return user; } /** * 根据 ID 查询单个用户 */ async findOneById(id: number): Promise { const user = await this.userRepository.findOne({ where: { userId: id }, }); if (!user) { throw new NotFoundException(`未找到ID为 ${id} 的用户`); } return user; } /** * 更新用户信息(不允许修改 username、openId、unionId) */ async update(id: number, updateUserDto: UpdateUserDto): Promise { const user = await this.findOneById(id); // 如果更新邮箱,检查是否与其他用户冲突 if (updateUserDto.email && updateUserDto.email !== user.email) { const existingByEmail = await this.userRepository.findOne({ where: { email: updateUserDto.email }, }); if (existingByEmail) { throw new ConflictException( `邮箱 "${updateUserDto.email}" 已存在`, ); } } // 如果更新 phone,检查是否与其他用户冲突 if (updateUserDto.phone && updateUserDto.phone !== user.phone) { const existingByPhone = await this.userRepository.findOne({ where: { phone: updateUserDto.phone }, }); if (existingByPhone) { throw new ConflictException( `手机号 "${updateUserDto.phone}" 已存在`, ); } } // 更新用户信息 Object.assign(user, updateUserDto); return this.userRepository.save(user); } /** * 修改密码(需要先验证旧密码) */ async changePassword( id: number, changePasswordDto: ChangePasswordDto, ): Promise { const user = await this.findOneById(id); // 验证旧密码 const isOldPasswordValid = await bcrypt.compare( changePasswordDto.oldPassword, user.passwordHash, ); if (!isOldPasswordValid) { throw new BadRequestException('旧密码错误'); } // 加密新密码 const saltRounds = 10; const newPasswordHash = await bcrypt.hash( changePasswordDto.newPassword, saltRounds, ); // 更新密码 user.passwordHash = newPasswordHash; await this.userRepository.save(user); } /** * 删除用户(软删除,更新状态为 deleted) */ async remove(id: number): Promise { const user = await this.findOneById(id); user.status = 'deleted'; await this.userRepository.save(user); } }