lrj
昨天 9f8395fab13ca4b230a0f7d62636e209745c91d4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
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<User> 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<User> findByPhone(String phone) {
        return userRepository.findByPhone(phone);
    }
 
    /**
     * 保存用户
     */
    public User save(User user) {
        return userRepository.save(user);
    }
 
    /**
     * 根据ID查找用户
     */
    public Optional<User> 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<User> 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("用户关联数据迁移完成");
    }
}