package com.example.copykamanotes.service.impl; import com.example.copykamanotes.annotation.NeedLogin; import com.example.copykamanotes.mapper.UserMapper; import com.example.copykamanotes.model.base.ApiResponse; import com.example.copykamanotes.model.base.Pagination; import com.example.copykamanotes.model.dto.user.LoginRequest; import com.example.copykamanotes.model.dto.user.RegisterRequest; import com.example.copykamanotes.model.dto.user.UpdateUserRequest; import com.example.copykamanotes.model.dto.user.UserQueryParam; import com.example.copykamanotes.model.entity.User; import com.example.copykamanotes.model.vo.user.AvatarVO; import com.example.copykamanotes.model.vo.user.LoginUserVO; import com.example.copykamanotes.model.vo.user.RegisterVO; import com.example.copykamanotes.model.vo.user.UserVO; import com.example.copykamanotes.scope.RequestScopeData; import com.example.copykamanotes.service.EmailService; import com.example.copykamanotes.service.FileService; import com.example.copykamanotes.service.UserService; import com.example.copykamanotes.utils.ApiResponseUtil; import com.example.copykamanotes.utils.JwtUtil; import com.example.copykamanotes.utils.PaginationUtil; import com.google.protobuf.Api; import lombok.extern.log4j.Log4j2; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @Log4j2 @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private PasswordEncoder passwordEncoder; @Autowired private JwtUtil jwtUtil; @Autowired private RequestScopeData requestScopeData; @Autowired private FileService fileService; @Autowired private EmailService emailService; @Override @Transactional(rollbackFor = Exception.class) public ApiResponse register(RegisterRequest registerRequest) { User existingUser = userMapper.findByAccount(registerRequest.getAccount()); if (existingUser != null) { return ApiResponseUtil.error("账号重复"); } if (registerRequest.getEmail() != null && !registerRequest.getEmail().isEmpty()) { // 验证邮箱是否重复 existingUser = userMapper.findByEmail(registerRequest.getEmail()); if (existingUser != null) { return ApiResponseUtil.error("邮箱重复"); } // if (registerRequest.getVerifyCode() == null || registerRequest.getVerifyCode().isEmpty()) { // return ApiResponseUtil.error("验证码不能为空"); // } // // if (!emailService.verifyCode(registerRequest.getEmail(), "register", registerRequest.getVerifyCode())) { // return ApiResponseUtil.error("验证码错误"); // } } User user = new User(); BeanUtils.copyProperties(registerRequest, user); user.setPassword(passwordEncoder.encode(registerRequest.getPassword())); user.setEmailVerified(registerRequest.getEmail() != null && !registerRequest.getEmail().isEmpty()); try { userMapper.insert(user); String token = jwtUtil.generateToken(user.getUserId()); RegisterVO registerVO = new RegisterVO(); BeanUtils.copyProperties(user, registerVO); userMapper.updateLastLoginAt(user.getUserId()); return ApiResponseUtil.success("注册成功", registerVO, token); } catch (Exception e) { log.error("注册失败", e); return ApiResponseUtil.error("注册失败,请稍后再试"); } } @Override public ApiResponse login(LoginRequest loginRequest) { User user = null; if (loginRequest.getAccount() != null && !loginRequest.getAccount().isEmpty()) { user = userMapper.findByAccount(loginRequest.getAccount()); } else if (loginRequest.getEmail() != null && !loginRequest.getEmail().isEmpty()) { user = userMapper.findByEmail(loginRequest.getEmail()); } else { return ApiResponseUtil.error("账号或邮箱不能为空"); } if (user == null) { return ApiResponseUtil.error("账号或邮箱不存在"); } if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) { return ApiResponseUtil.error("密码错误"); } String token = jwtUtil.generateToken(user.getUserId()); LoginUserVO loginUserVO = new LoginUserVO(); BeanUtils.copyProperties(user, loginUserVO); userMapper.updateLastLoginAt(user.getUserId()); return ApiResponseUtil.success("登录成功", loginUserVO, token); } @Override public ApiResponse whoami() { Long userId = requestScopeData.getUserId(); if (userId == null) { return ApiResponseUtil.error("未登录"); } try { User user = userMapper.findById(userId); if (user == null) { return ApiResponseUtil.error("用户不存在"); } String newToken = jwtUtil.generateToken(userId); if (newToken == null) { return ApiResponseUtil.error("token生成失败"); } LoginUserVO loginUserVO = new LoginUserVO(); BeanUtils.copyProperties(user, loginUserVO); return ApiResponseUtil.success("获取用户信息成功", loginUserVO, newToken); } catch (Exception e) { log.error("获取用户信息失败", e); return ApiResponseUtil.error("获取用户信息失败"); } } @Override public ApiResponse getUserInfo(Long userId) { User user = userMapper.findById(userId); if (user == null) { return ApiResponseUtil.error("用户不存在"); } UserVO userVO = new UserVO(); BeanUtils.copyProperties(user, userVO); return ApiResponseUtil.success("获取用户信息成功", userVO); } @Override @Transactional @NeedLogin public ApiResponse updateUserInfo(UpdateUserRequest updateUserRequest) { Long userId = requestScopeData.getUserId(); if (userId == null) { return ApiResponseUtil.error("未登录"); } User user = new User(); BeanUtils.copyProperties(updateUserRequest, user); user.setUserId(userId); try { userMapper.update(user); return ApiResponseUtil.success("更新用户信息成功"); } catch (Exception e) { log.error("更新用户信息失败", e); return ApiResponseUtil.error("更新用户信息失败"); } } @Override public Map getUserMapByIds(List authorIds) { if (authorIds.isEmpty()) return Collections.emptyMap(); List users = userMapper.findByIds(authorIds); return users.stream().collect(Collectors.toMap(User::getUserId, user -> user)); } @Override public ApiResponse> getUserList(UserQueryParam userQueryParam) { // 分页数据 int total = userMapper.countByQueryParam(userQueryParam); int offset = PaginationUtil.calculateOffset(userQueryParam.getPage(), userQueryParam.getPageSize()); Pagination pagination = new Pagination(userQueryParam.getPage(), userQueryParam.getPageSize(), total); try { List users = userMapper.findByQueryParam(userQueryParam, userQueryParam.getPageSize(), offset); return ApiResponseUtil.success("获取用户列表成功", users, pagination); } catch (Exception e) { return ApiResponseUtil.error(e.getMessage()); } } @Override public ApiResponse uploadAvatar(MultipartFile file) { try { String url = fileService.uploadImage(file); AvatarVO avatarVO = new AvatarVO(); avatarVO.setAvatarUrl(url); return ApiResponseUtil.success("上传成功", avatarVO); } catch (Exception e) { log.error("上传失败", e); return ApiResponseUtil.error("上传失败"); } } @Override public ApiResponse updateUserPassword(String oldPassword, String newPassword) { Long userId = requestScopeData.getUserId(); if (userId == null) { return ApiResponseUtil.error("未登录"); } User user = null; user = userMapper.findById(userId); if (user == null || !passwordEncoder.matches(oldPassword, user.getPassword())) { return ApiResponseUtil.error("旧密码错误"); } if (Objects.equals(oldPassword, newPassword)) { return ApiResponseUtil.error("新密码不能与旧密码相同"); } user.setPassword(passwordEncoder.encode(newPassword)); try { userMapper.updatePassword(user.getUserId(), user.getPassword()); return ApiResponseUtil.success("更新密码成功"); } catch (Exception e) { log.error("更新密码失败", e); return ApiResponseUtil.error("更新密码失败"); } } }