package com.rongyichuang.user.service; import com.rongyichuang.user.entity.User; import com.rongyichuang.user.repository.UserRepository; import com.rongyichuang.employee.repository.EmployeeRepository; import com.rongyichuang.judge.repository.JudgeRepository; import com.rongyichuang.player.repository.PlayerRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Optional; /** * 用户服务类 */ @Service @Transactional public class UserService { private static final Logger logger = LoggerFactory.getLogger(UserService.class); @Autowired private UserRepository userRepository; @Autowired private EmployeeRepository employeeRepository; @Autowired private JudgeRepository judgeRepository; @Autowired private PlayerRepository playerRepository; private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); /** * 根据手机号查找或创建用户 * 如果用户存在,更新姓名和密码(如果提供了密码) * 如果用户不存在,创建新用户 * * @param phone 手机号 * @param name 姓名 * @param password 密码(可以为null,表示不更新密码) * @return 用户实体 */ public User findOrCreateUserByPhone(String phone, String name, String password) { Optional existingUser = userRepository.findByPhone(phone); if (existingUser.isPresent()) { // 用户存在,更新姓名和密码(如果提供了密码) User user = existingUser.get(); user.setName(name); if (password != null && !password.trim().isEmpty()) { user.setPassword(passwordEncoder.encode(password)); } return userRepository.save(user); } else { // 用户不存在,创建新用户 User newUser = new User(); newUser.setName(name); newUser.setPhone(phone); if (password != null && !password.trim().isEmpty()) { newUser.setPassword(passwordEncoder.encode(password)); } else { // 如果没有提供密码,设置一个默认密码 newUser.setPassword(passwordEncoder.encode("123456")); } return userRepository.save(newUser); } } /** * 根据手机号查找用户 */ public Optional findByPhone(String phone) { return userRepository.findByPhone(phone); } /** * 保存用户 */ public User save(User user) { return userRepository.save(user); } /** * 根据ID查找用户 */ public Optional findById(Long id) { return userRepository.findById(id); } /** * 保存用户手机号码 * 核心逻辑: * 1. 查询当前t_user里面是否存在相同的电话号码,如果没有,就更新到当前user里面 * 2. 如果存在相同的电话号码,并且对应user的openid是null,那么清空原来user的phone设置为null, * 把新的电话号码更新到当前用户的phone字段,同时更新t_player、t_judge、t_employee关联的user_id到新的user_id * * @param currentUserId 当前用户ID * @param phone 要保存的手机号码 * @return 更新后的用户实体 */ @Transactional public User saveUserPhone(Long currentUserId, String phone) { logger.info("开始处理用户手机号码保存,用户ID: {}, 手机号: {}", currentUserId, phone); // 获取当前用户 User currentUser = userRepository.findById(currentUserId) .orElseThrow(() -> new RuntimeException("用户不存在,ID: " + currentUserId)); // 检查是否存在相同手机号的用户 Optional existingPhoneUser = userRepository.findByPhone(phone); if (existingPhoneUser.isEmpty()) { // 情况1:没有其他用户使用这个手机号,直接更新当前用户 logger.info("手机号 {} 未被使用,直接更新到用户 {}", phone, currentUserId); currentUser.setPhone(phone); return userRepository.save(currentUser); } else { User phoneUser = existingPhoneUser.get(); // 如果是同一个用户,无需处理 if (phoneUser.getId().equals(currentUserId)) { logger.info("手机号 {} 已属于当前用户 {},无需更新", phone, currentUserId); return currentUser; } // 情况2:存在相同手机号的用户,且该用户的openid为null if (phoneUser.getWxOpenid() == null || phoneUser.getWxOpenid().trim().isEmpty()) { logger.info("发现手机号 {} 被用户 {} 使用,但该用户无openid,开始数据迁移", phone, phoneUser.getId()); // 迁移关联数据 migrateUserRelatedData(phoneUser.getId(), currentUserId); // 清空原用户的手机号 phoneUser.setPhone(null); userRepository.save(phoneUser); logger.info("已清空原用户 {} 的手机号", phoneUser.getId()); // 更新当前用户的手机号 currentUser.setPhone(phone); User savedUser = userRepository.save(currentUser); logger.info("已将手机号 {} 更新到当前用户 {}", phone, currentUserId); return savedUser; } else { // 情况3:存在相同手机号的用户,且该用户有openid,不能覆盖 logger.warn("手机号 {} 已被用户 {} 使用,且该用户有openid,无法更新", phone, phoneUser.getId()); throw new RuntimeException("手机号已被其他微信用户使用,无法更新"); } } } /** * 迁移用户关联数据 * 将原用户的员工、评委、学员信息迁移到新用户 * * @param fromUserId 原用户ID * @param toUserId 目标用户ID */ private void migrateUserRelatedData(Long fromUserId, Long toUserId) { logger.info("开始迁移用户关联数据,从用户 {} 到用户 {}", fromUserId, toUserId); // 迁移员工信息 employeeRepository.findByUserId(fromUserId).ifPresent(employee -> { logger.info("迁移员工信息,员工ID: {}, 姓名: {}", employee.getId(), employee.getName()); employee.setUserId(toUserId); employeeRepository.save(employee); }); // 迁移评委信息 judgeRepository.findByUserId(fromUserId).ifPresent(judge -> { logger.info("迁移评委信息,评委ID: {}, 姓名: {}", judge.getId(), judge.getName()); judge.setUserId(toUserId); judgeRepository.save(judge); }); // 迁移学员信息 playerRepository.findByUserId(fromUserId).ifPresent(player -> { logger.info("迁移学员信息,学员ID: {}, 姓名: {}", player.getId(), player.getName()); player.setUserId(toUserId); playerRepository.save(player); }); logger.info("用户关联数据迁移完成"); } }