package com.njuzr.eaibackend.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.njuzr.eaibackend.dto.user.PasswordChangeDTO; import com.njuzr.eaibackend.dto.user.UserDTO; import com.njuzr.eaibackend.dto.user.UserRegisterDTO; import com.njuzr.eaibackend.dto.user.UserUpdateDTO; import com.njuzr.eaibackend.enums.Role; import com.njuzr.eaibackend.exception.MyException; import com.njuzr.eaibackend.mapper.UserMapper; import com.njuzr.eaibackend.po.User; import com.njuzr.eaibackend.service.UserService; import com.njuzr.eaibackend.utils.ModelMapperUtil; import com.njuzr.eaibackend.utils.PageMapperUtil; import com.njuzr.eaibackend.vo.UserVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpStatus; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private RedisTemplate redisTemplate; private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); @Override public IPage searchUsers(Page page, Long id, String name, String officialNumber, Role role) { QueryWrapper queryWrapper = new QueryWrapper<>(); // 设置查询条件 // 禁止访问查询ADMIN用户 if (role == Role.ADMIN) { throw new MyException(HttpStatus.FORBIDDEN.value(), HttpStatus.FORBIDDEN.getReasonPhrase() + ":" + "被拒绝"); } queryWrapper .eq(Objects.nonNull(id), "id", id) .like(StringUtils.isNotBlank(name), "name", name) .eq(StringUtils.isNotBlank(officialNumber), "official_number", officialNumber) .eq(Objects.nonNull(role), "role", role); IPage targets = userMapper.selectPage(page, queryWrapper); // selectPage是内置的方法 // targets.total如果为0,则说明没有符合条件的用户,但是不报错,由前端自行处理异常。 return PageMapperUtil.convert(targets, record -> ModelMapperUtil.map(record, UserVO.class)); } @Override public UserVO createUser(UserRegisterDTO userDTO) { // 从Redis中获取验证码 final String key = "registerVerifyCode:" + userDTO.getOfficialEmail(); String storedCode = (String) redisTemplate.opsForValue().get(key); if (storedCode == null) { throw new MyException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase() + ":" + "验证码已过期"); } // 验证码校验 if (storedCode.equals(userDTO.getVerifyCode())) { // 检查邮箱和学号是否已存在 if (!isOfficialNumberNotExists(userDTO.getOfficialNumber())) { throw new MyException(HttpStatus.BAD_REQUEST.value(), "学号已注册"); } if (!isEmailNotExists(userDTO.getOfficialEmail())) { throw new MyException(HttpStatus.BAD_REQUEST.value(), "邮箱已注册"); } User targetUser = ModelMapperUtil.map(userDTO, User.class); targetUser.setPassword(new BCryptPasswordEncoder().encode(targetUser.getPassword())); // 密码加密存储 targetUser.setCreateTime(new Date()); // 设置创建时间 int state = userMapper.insert(targetUser); log.info("state: {}", state); log.info("User创建完毕,User对象如下:" + targetUser); redisTemplate.delete(key); //注册成功后删除验证码 return ModelMapperUtil.map(targetUser, UserVO.class); } else { throw new MyException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase() + ":" + "验证码错误"); } } @Override public UserVO createUserByPortal(UserRegisterDTO userDTO) { User targetUser = ModelMapperUtil.map(userDTO, User.class); targetUser.setCreateTime(new Date()); // 设置创建时间 int state = userMapper.insert(targetUser); log.info("state: {}", state); log.info("User创建完毕,User对象如下:" + targetUser); return ModelMapperUtil.map(targetUser, UserVO.class); } /** * 更新用户信息 * * @param userDTO * @return */ @Override public UserVO updateUser(Long id, UserUpdateDTO userDTO) { UserDTO opeUser = ModelMapperUtil.map(userDTO, UserDTO.class); User user = ModelMapperUtil.map(userDTO, User.class); user.setId(id); try { int status = userMapper.updateUser(user); if (status > 0) { return ModelMapperUtil.map(userMapper.selectById(user.getId()), UserVO.class); } } catch (Exception e) { log.error("数据库更新错误,错误如下:" + e.getMessage()); throw new MyException(HttpStatus.INTERNAL_SERVER_ERROR.value(), HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase() + ":" + "数据库更新失败"); } return null; } @Override public UserVO updateUserByPid(Integer pid, UserUpdateDTO userDTO) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("pid", pid); User user = userMapper.selectOne(queryWrapper); return this.updateUser(user.getId(), userDTO); } /** * 更新密码 */ @Override public void updatePassword(PasswordChangeDTO passwordChangeDTO) throws MyException { User user = userMapper.selectByOfficialEmail(passwordChangeDTO.getOfficialEmail()); if (user == null) { log.error("用户不存在"); throw new MyException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase() + ":" + "找不到用户"); } // 从Redis中获取验证码 final String key = "passwordChangeVerifyCode:" + passwordChangeDTO.getOfficialEmail(); String storedCode = (String) redisTemplate.opsForValue().get(key); if (storedCode == null) { throw new MyException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase() + ":" + "验证码已过期"); } // 验证码校验 if (storedCode.equals(passwordChangeDTO.getVerifyCode())) { String encodedNewPassword = passwordEncoder.encode(passwordChangeDTO.getPassword()); int code = userMapper.updatePassword(user.getId(), encodedNewPassword); if (code == 1) { log.info("用户更新成功"); } redisTemplate.delete(key); //成功后删除验证码 } else { throw new MyException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase() + ":" + "验证码错误"); } } @Override public boolean userExists(Integer pid) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("pid", pid); return userMapper.exists(queryWrapper); } /** * 查看学号是否不存在 * * @param officialNumber 学号 * @return true表示不存在,false表示存在 */ private boolean isOfficialNumberNotExists(String officialNumber) throws MyException { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("official_number", officialNumber); User existingUser = userMapper.selectOne(queryWrapper); if (existingUser != null) { log.error("用户已存在,学号{}重复", officialNumber); throw new MyException(400, "用户已存在,请检查学号信息"); } return true; } /** * 查看邮箱是否不存在 * * @param email 邮箱 * @return true表示不存在,false表示存在 */ private boolean isEmailNotExists(String email) throws MyException { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("official_email", email); User existingUser = userMapper.selectOne(queryWrapper); if (existingUser != null) { log.error("用户已存在,邮箱{}重复", email); throw new MyException(400, "用户已存在,请检查邮箱信息"); } return true; } @Override public String getNameById(Long id) { if (id == null) return null; try { return userMapper.selectNameById(id); } catch (Exception e) { return null; } } @Override public Map getNamesByIds(Collection ids) { if (ids == null || ids.isEmpty()) return Collections.emptyMap(); QueryWrapper wrapper = new QueryWrapper<>(); wrapper.in("id", ids); List users = userMapper.selectList(wrapper); if (users == null || users.isEmpty()) return Collections.emptyMap(); return users.stream().collect(Collectors.toMap(User::getId, User::getName, (a,b)->a)); } }