Kaynağa Gözat

增加与ai大模型对话

wwh 3 hafta önce
ebeveyn
işleme
dd4b6d12df

+ 1 - 0
doc/灵活用工-mysql.sql

@@ -38,6 +38,7 @@ CREATE TABLE `fe_user` (
38 38
   PRIMARY KEY (`id`),
39 39
   UNIQUE KEY `uk_fe_user_openid` (`openid`, `del_flag`),
40 40
   UNIQUE KEY `uk_fe_user_username` (`username`, `del_flag`),
41
+  UNIQUE KEY `uk_fe_user_mobile_enc` (`mobile_enc`(128), `del_flag`),
41 42
   KEY `idx_fe_user_type` (`user_type`, `status`)
42 43
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信用户主表,企业主与临时工共用账号体系,通过 user_type 区分身份。支撑微信小程序 code2session 登录与 Session 鉴权,是 fe_enterprise_user、fe_conversation、fe_worker 等表的用户外键来源。敏感手机号仅存密文与脱敏值,禁止明文入库。';
43 44
 

+ 1 - 0
doc/灵活用工.sql

@@ -60,6 +60,7 @@ CREATE TABLE fe_user (
60 60
 );
61 61
 CREATE UNIQUE INDEX uk_fe_user_openid ON fe_user (openid) WHERE del_flag = 0;
62 62
 CREATE UNIQUE INDEX uk_fe_user_username ON fe_user (username) WHERE del_flag = 0 AND username IS NOT NULL;
63
+CREATE UNIQUE INDEX uk_fe_user_mobile_enc ON fe_user (mobile_enc, del_flag);
63 64
 CREATE INDEX idx_fe_user_type ON fe_user (user_type, status);
64 65
 
65 66
 

+ 73 - 28
huimv-employment/fe-service/src/main/java/com/huimv/employment/service/auth/AuthService.java

@@ -15,6 +15,9 @@ import com.huimv.employment.service.auth.dto.WechatLoginRequest;
15 15
 import com.huimv.employment.service.config.SecurityProperties;
16 16
 import com.huimv.employment.service.sms.SmsCodeService;
17 17
 import com.huimv.employment.service.wechat.WeChatMiniAppService;
18
+import org.slf4j.Logger;
19
+import org.slf4j.LoggerFactory;
20
+import org.springframework.dao.DuplicateKeyException;
18 21
 import org.springframework.stereotype.Service;
19 22
 import org.springframework.transaction.annotation.Transactional;
20 23
 import org.springframework.util.StringUtils;
@@ -27,6 +30,8 @@ import java.time.LocalDateTime;
27 30
 @Service
28 31
 public class AuthService {
29 32
 
33
+    private static final Logger log = LoggerFactory.getLogger(AuthService.class);
34
+
30 35
     private static final String STATUS_ACTIVE = "active";
31 36
     private static final String STATUS_DISABLED = "disabled";
32 37
 
@@ -60,21 +65,14 @@ public class AuthService {
60 65
         String mobileEnc = AesUtils.encrypt(request.getMobile(), securityProperties.getMobileAesKey());
61 66
         String mobileMask = MobileUtils.mask(request.getMobile());
62 67
 
63
-        FeUser user = feUserMapper.selectOne(new LambdaQueryWrapper<FeUser>()
64
-                .eq(FeUser::getMobileEnc, mobileEnc)
65
-                .last("LIMIT 1"));
66
-
67
-        if (user == null) {
68
-            user = createUserBySms(mobileEnc, mobileMask, request.getUserType());
69
-        } else {
70
-            ensureUserActive(user);
71
-            if (!request.getUserType().equals(user.getUserType())) {
72
-                user.setUserType(request.getUserType());
73
-            }
74
-            user.setMobileMask(mobileMask);
75
-            touchLogin(user);
76
-            feUserMapper.updateById(user);
68
+        FeUser user = findOrCreateByMobile(mobileEnc, mobileMask, request.getUserType());
69
+        ensureUserActive(user);
70
+        if (!request.getUserType().equals(user.getUserType())) {
71
+            user.setUserType(request.getUserType());
77 72
         }
73
+        user.setMobileMask(mobileMask);
74
+        touchLogin(user);
75
+        feUserMapper.updateById(user);
78 76
 
79 77
         return buildLoginResponse(user);
80 78
     }
@@ -83,24 +81,71 @@ public class AuthService {
83 81
     public LoginResponse loginByWechat(WechatLoginRequest request) {
84 82
         WeChatMiniAppService.WxSession session = weChatMiniAppService.code2Session(request.getCode());
85 83
 
86
-        FeUser user = feUserMapper.selectOne(new LambdaQueryWrapper<FeUser>()
87
-                .eq(FeUser::getOpenid, session.getOpenid())
88
-                .last("LIMIT 1"));
84
+        FeUser user = findOrCreateByOpenid(session, request.getUserType());
85
+        ensureUserActive(user);
86
+        if (!request.getUserType().equals(user.getUserType())) {
87
+            user.setUserType(request.getUserType());
88
+        }
89
+        user.setUnionid(session.getUnionid());
90
+        user.setSessionKey(session.getSessionKey());
91
+        touchLogin(user);
92
+        feUserMapper.updateById(user);
93
+
94
+        return buildLoginResponse(user);
95
+    }
89 96
 
90
-        if (user == null) {
91
-            user = createUserByWechat(session, request.getUserType());
92
-        } else {
93
-            ensureUserActive(user);
94
-            if (!request.getUserType().equals(user.getUserType())) {
95
-                user.setUserType(request.getUserType());
97
+    /**
98
+     * 按加密手机号查找或创建用户;并发 insert 冲突时重查已存在记录。
99
+     */
100
+    private FeUser findOrCreateByMobile(String mobileEnc, String mobileMask, String userType) {
101
+        FeUser user = findByMobileEnc(mobileEnc);
102
+        if (user != null) {
103
+            return user;
104
+        }
105
+        try {
106
+            return createUserBySms(mobileEnc, mobileMask, userType);
107
+        } catch (DuplicateKeyException ex) {
108
+            log.debug("Concurrent sms login insert for mobile_enc, re-select", ex);
109
+            user = findByMobileEnc(mobileEnc);
110
+            if (user == null) {
111
+                log.error("DuplicateKey on mobile_enc but re-select returned null", ex);
112
+                throw new BizException(ErrorCode.INTERNAL_ERROR);
96 113
             }
97
-            user.setUnionid(session.getUnionid());
98
-            user.setSessionKey(session.getSessionKey());
99
-            touchLogin(user);
100
-            feUserMapper.updateById(user);
114
+            return user;
101 115
         }
116
+    }
102 117
 
103
-        return buildLoginResponse(user);
118
+    /**
119
+     * 按 openid 查找或创建用户;并发 insert 冲突时重查已存在记录。
120
+     */
121
+    private FeUser findOrCreateByOpenid(WeChatMiniAppService.WxSession session, String userType) {
122
+        FeUser user = findByOpenid(session.getOpenid());
123
+        if (user != null) {
124
+            return user;
125
+        }
126
+        try {
127
+            return createUserByWechat(session, userType);
128
+        } catch (DuplicateKeyException ex) {
129
+            log.debug("Concurrent wechat login insert for openid, re-select", ex);
130
+            user = findByOpenid(session.getOpenid());
131
+            if (user == null) {
132
+                log.error("DuplicateKey on openid but re-select returned null", ex);
133
+                throw new BizException(ErrorCode.INTERNAL_ERROR);
134
+            }
135
+            return user;
136
+        }
137
+    }
138
+
139
+    private FeUser findByMobileEnc(String mobileEnc) {
140
+        return feUserMapper.selectOne(new LambdaQueryWrapper<FeUser>()
141
+                .eq(FeUser::getMobileEnc, mobileEnc)
142
+                .last("LIMIT 1"));
143
+    }
144
+
145
+    private FeUser findByOpenid(String openid) {
146
+        return feUserMapper.selectOne(new LambdaQueryWrapper<FeUser>()
147
+                .eq(FeUser::getOpenid, openid)
148
+                .last("LIMIT 1"));
104 149
     }
105 150
 
106 151
     private FeUser createUserBySms(String mobileEnc, String mobileMask, String userType) {