Преглед изворни кода

增加与ai大模型对话

wwh пре 3 недеља
родитељ
комит
dd4b6d12df

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

@@ -38,6 +38,7 @@ CREATE TABLE `fe_user` (
38
   PRIMARY KEY (`id`),
38
   PRIMARY KEY (`id`),
39
   UNIQUE KEY `uk_fe_user_openid` (`openid`, `del_flag`),
39
   UNIQUE KEY `uk_fe_user_openid` (`openid`, `del_flag`),
40
   UNIQUE KEY `uk_fe_user_username` (`username`, `del_flag`),
40
   UNIQUE KEY `uk_fe_user_username` (`username`, `del_flag`),
41
+  UNIQUE KEY `uk_fe_user_mobile_enc` (`mobile_enc`(128), `del_flag`),
41
   KEY `idx_fe_user_type` (`user_type`, `status`)
42
   KEY `idx_fe_user_type` (`user_type`, `status`)
42
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信用户主表,企业主与临时工共用账号体系,通过 user_type 区分身份。支撑微信小程序 code2session 登录与 Session 鉴权,是 fe_enterprise_user、fe_conversation、fe_worker 等表的用户外键来源。敏感手机号仅存密文与脱敏值,禁止明文入库。';
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
 CREATE UNIQUE INDEX uk_fe_user_openid ON fe_user (openid) WHERE del_flag = 0;
61
 CREATE UNIQUE INDEX uk_fe_user_openid ON fe_user (openid) WHERE del_flag = 0;
62
 CREATE UNIQUE INDEX uk_fe_user_username ON fe_user (username) WHERE del_flag = 0 AND username IS NOT NULL;
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
 CREATE INDEX idx_fe_user_type ON fe_user (user_type, status);
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
 import com.huimv.employment.service.config.SecurityProperties;
15
 import com.huimv.employment.service.config.SecurityProperties;
16
 import com.huimv.employment.service.sms.SmsCodeService;
16
 import com.huimv.employment.service.sms.SmsCodeService;
17
 import com.huimv.employment.service.wechat.WeChatMiniAppService;
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
 import org.springframework.stereotype.Service;
21
 import org.springframework.stereotype.Service;
19
 import org.springframework.transaction.annotation.Transactional;
22
 import org.springframework.transaction.annotation.Transactional;
20
 import org.springframework.util.StringUtils;
23
 import org.springframework.util.StringUtils;
@@ -27,6 +30,8 @@ import java.time.LocalDateTime;
27
 @Service
30
 @Service
28
 public class AuthService {
31
 public class AuthService {
29
 
32
 
33
+    private static final Logger log = LoggerFactory.getLogger(AuthService.class);
34
+
30
     private static final String STATUS_ACTIVE = "active";
35
     private static final String STATUS_ACTIVE = "active";
31
     private static final String STATUS_DISABLED = "disabled";
36
     private static final String STATUS_DISABLED = "disabled";
32
 
37
 
@@ -60,21 +65,14 @@ public class AuthService {
60
         String mobileEnc = AesUtils.encrypt(request.getMobile(), securityProperties.getMobileAesKey());
65
         String mobileEnc = AesUtils.encrypt(request.getMobile(), securityProperties.getMobileAesKey());
61
         String mobileMask = MobileUtils.mask(request.getMobile());
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
         return buildLoginResponse(user);
77
         return buildLoginResponse(user);
80
     }
78
     }
@@ -83,24 +81,71 @@ public class AuthService {
83
     public LoginResponse loginByWechat(WechatLoginRequest request) {
81
     public LoginResponse loginByWechat(WechatLoginRequest request) {
84
         WeChatMiniAppService.WxSession session = weChatMiniAppService.code2Session(request.getCode());
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
     private FeUser createUserBySms(String mobileEnc, String mobileMask, String userType) {
151
     private FeUser createUserBySms(String mobileEnc, String mobileMask, String userType) {