From 4f367056ab0e73d044e920d44b1d7dd0c8b65d80 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期二, 12 五月 2026 14:25:28 +0800
Subject: [PATCH] fix:注册流程优化、屏蔽账号密码登录、已登录后token永不过期

---
 tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/register/service/AppRegisterService.java |   95 ++++++++++++++++++++++++++++++-----------------
 1 files changed, 61 insertions(+), 34 deletions(-)

diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/register/service/AppRegisterService.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/register/service/AppRegisterService.java
index 384f3e2..8e06c55 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/register/service/AppRegisterService.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/register/service/AppRegisterService.java
@@ -2,7 +2,10 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.tcm.training.admin.app.auth.service.AppAuthSessionService;
 import com.tcm.training.admin.app.auth.service.AppSmsCodeService;
+import com.tcm.training.admin.app.auth.vo.AppLoginResponse;
+import com.tcm.training.admin.app.auth.vo.AppLoginUserVO;
 import com.tcm.training.admin.app.auth.vo.AppSmsCodeSendResponse;
 import com.tcm.training.admin.app.integration.haizhentong.entity.HztAppUser;
 import com.tcm.training.admin.app.integration.haizhentong.entity.HztClinic;
@@ -16,14 +19,13 @@
 import com.tcm.training.admin.app.register.vo.AppRegisterOperatorPrepareResponse;
 import com.tcm.training.admin.app.register.vo.AppRegisterRegionDatasetVO;
 import com.tcm.training.admin.app.register.vo.AppRegisterRegionOptionVO;
-import com.tcm.training.admin.app.register.vo.AppRegisterResultVO;
 import com.tcm.training.admin.common.PhoneMasker;
 import com.tcm.training.admin.live.entity.Clinic;
 import com.tcm.training.admin.live.mapper.ClinicMapper;
 import com.tcm.training.admin.member.entity.AppUser;
 import com.tcm.training.admin.member.mapper.UserMapper;
+import cn.dev33.satoken.stp.SaTokenInfo;
 import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -40,7 +42,6 @@
 public class AppRegisterService {
 
     private static final Pattern PHONE_PATTERN = Pattern.compile("^1\\d{10}$");
-    private static final Pattern PASSWORD_PATTERN = Pattern.compile("^(?![0-9]+$)(?![a-zA-Z]+$)(?![^0-9a-zA-Z]+$).{8,32}$");
     private static final String REGISTER_TICKET_CACHE_PREFIX = "app:register:operator:";
     private static final String INVITE_CODE_CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
     private static final int INVITE_CODE_LENGTH = 6;
@@ -48,8 +49,8 @@
 
     private final UserMapper userMapper;
     private final ClinicMapper clinicMapper;
-    private final BCryptPasswordEncoder passwordEncoder;
     private final AppSmsCodeService appSmsCodeService;
+    private final AppAuthSessionService appAuthSessionService;
     private final AppRegisterRegionService appRegisterRegionService;
     private final HztAppUserMapper hztAppUserMapper;
     private final HztClinicMapper hztClinicMapper;
@@ -62,8 +63,8 @@
      */
     public AppRegisterService(UserMapper userMapper,
                               ClinicMapper clinicMapper,
-                              BCryptPasswordEncoder passwordEncoder,
                               AppSmsCodeService appSmsCodeService,
+                              AppAuthSessionService appAuthSessionService,
                               AppRegisterRegionService appRegisterRegionService,
                               HztAppUserMapper hztAppUserMapper,
                               HztClinicMapper hztClinicMapper,
@@ -72,8 +73,8 @@
                               AppShareService appShareService) {
         this.userMapper = userMapper;
         this.clinicMapper = clinicMapper;
-        this.passwordEncoder = passwordEncoder;
         this.appSmsCodeService = appSmsCodeService;
+        this.appAuthSessionService = appAuthSessionService;
         this.appRegisterRegionService = appRegisterRegionService;
         this.hztAppUserMapper = hztAppUserMapper;
         this.hztClinicMapper = hztClinicMapper;
@@ -109,9 +110,8 @@
      * 完成普通用户注册,并按需绑定上级诊所用户。
      * 普通用户注册会先查询海诊通数据源,因此这里不包裹本地事务,避免事务先绑定 master 导致跨库查询失效。
      */
-    public AppRegisterResultVO registerUser(AppRegisterUserRequest request) {
+    public AppLoginResponse registerUser(AppRegisterUserRequest request) {
         String phone = normalizePhone(request.getPhone());
-        String password = normalizePassword(request.getPassword());
         String inviteCode = normalizeInviteCode(request.getInviteCode());
         String bindTicket = normalizeBindTicket(request.getBindTicket());
 
@@ -120,7 +120,6 @@
 
         AppUser user = new AppUser();
         user.setPhone(phone);
-        user.setPassword(passwordEncoder.encode(password));
         user.setType(0);
         user.setStatus(1);
 
@@ -132,7 +131,7 @@
         bindSuperiorClinicIfNecessary(user, inviteCode, bindTicket);
 
         userMapper.insert(user);
-        return new AppRegisterResultVO(user.getId(), user.getType(), user.getClinicId(), null);
+        return createLoginResponse(user);
     }
 
     /**
@@ -140,13 +139,12 @@
      */
     public AppRegisterOperatorPrepareResponse prepareOperatorRegister(AppRegisterOperatorPrepareRequest request) {
         String phone = normalizePhone(request.getPhone());
-        String password = normalizePassword(request.getPassword());
 
         ensurePhoneAvailable(phone);
         appSmsCodeService.validateRegisterCode(phone, normalizeCode(request.getCode()));
 
         HztClinic hztClinic = findHztClinicByPhone(phone);
-        OperatorRegisterDraft draft = buildOperatorDraft(phone, password, hztClinic);
+        OperatorRegisterDraft draft = buildOperatorDraft(phone, hztClinic);
         String registerTicket = createRegisterTicket();
         cacheDraft(registerTicket, draft);
 
@@ -161,7 +159,7 @@
      * 完成经营者第二步,创建本地诊所与诊所用户。
      */
     @Transactional
-    public AppRegisterResultVO completeOperatorRegister(AppRegisterOperatorCompleteRequest request) {
+    public AppLoginResponse completeOperatorRegister(AppRegisterOperatorCompleteRequest request) {
         OperatorRegisterDraft draft = loadDraft(normalizeRegisterTicket(request.getRegisterTicket()));
         ensurePhoneAvailable(draft.getPhone());
 
@@ -184,14 +182,13 @@
         AppUser user = new AppUser();
         user.setNickname(clinic.getName());
         user.setPhone(draft.getPhone());
-        user.setPassword(draft.getEncodedPassword());
         user.setType(1);
         user.setStatus(1);
         user.setClinicId(clinic.getId());
         userMapper.insert(user);
 
         clearDraft(request.getRegisterTicket());
-        return new AppRegisterResultVO(user.getId(), user.getType(), clinic.getId(), clinic.getInviteCode());
+        return createLoginResponse(user);
     }
 
     /**
@@ -218,6 +215,42 @@
         }
         user.setClinicId(bindingTarget.getClinicId());
         user.setSuperiorClinicUserId(bindingTarget.getSuperiorClinicUserId());
+    }
+
+    /**
+     * 注册成功后立即建立 APP 登录态并返回统一登录响应。
+     */
+    private AppLoginResponse createLoginResponse(AppUser user) {
+        appAuthSessionService.login(user.getId());
+        return buildLoginResponse(user, appAuthSessionService.getTokenInfo());
+    }
+
+    /**
+     * 使用 Sa-Token 信息构造 APP 登录响应。
+     */
+    private AppLoginResponse buildLoginResponse(AppUser user, SaTokenInfo tokenInfo) {
+        return new AppLoginResponse(
+                tokenInfo.getTokenValue(),
+                "Bearer",
+                tokenInfo.getTokenTimeout(),
+                buildLoginUser(user)
+        );
+    }
+
+    /**
+     * 将注册后的 APP 用户实体转换为登录响应用户摘要。
+     */
+    private AppLoginUserVO buildLoginUser(AppUser user) {
+        AppLoginUserVO loginUser = new AppLoginUserVO();
+        loginUser.setId(user.getId());
+        loginUser.setNickname(resolveFallbackNickname(user));
+        loginUser.setPhone(user.getPhone());
+        loginUser.setAvatar(trimToNull(user.getAvatar()));
+        loginUser.setType(user.getType());
+        loginUser.setStatus(user.getStatus());
+        loginUser.setClinicId(user.getClinicId());
+        loginUser.setMemberExpireAt(user.getMemberExpireAt());
+        return loginUser;
     }
 
     /**
@@ -258,12 +291,11 @@
     }
 
     /**
-     * 构造经营者注册草稿,避免第二步再次输入验证码与密码。
+     * 构造经营者注册草稿,避免第二步再次输入验证码。
      */
-    private OperatorRegisterDraft buildOperatorDraft(String phone, String password, HztClinic hztClinic) {
+    private OperatorRegisterDraft buildOperatorDraft(String phone, HztClinic hztClinic) {
         OperatorRegisterDraft draft = new OperatorRegisterDraft();
         draft.setPhone(phone);
-        draft.setEncodedPassword(passwordEncoder.encode(password));
         if (hztClinic == null) {
             return draft;
         }
@@ -423,6 +455,17 @@
     }
 
     /**
+     * 优先使用用户昵称,缺失时回退到手机号脱敏昵称。
+     */
+    private String resolveFallbackNickname(AppUser user) {
+        String nickname = trimToNull(user.getNickname());
+        if (nickname != null) {
+            return nickname;
+        }
+        return resolveFallbackNickname(user.getPhone());
+    }
+
+    /**
      * 归一化并校验手机号格式。
      */
     private String normalizePhone(String phone) {
@@ -440,20 +483,6 @@
         String normalized = trimToNull(code);
         if (normalized == null) {
             throw new IllegalArgumentException("请输入验证码");
-        }
-        return normalized;
-    }
-
-    /**
-     * 归一化并校验注册密码规则。
-     */
-    private String normalizePassword(String password) {
-        String normalized = trimToNull(password);
-        if (normalized == null) {
-            throw new IllegalArgumentException("请输入密码");
-        }
-        if (!PASSWORD_PATTERN.matcher(normalized).matches()) {
-            throw new IllegalArgumentException("密码需为8-32位,且包含数字、字母、符号至少2种");
         }
         return normalized;
     }
@@ -515,8 +544,6 @@
     public static class OperatorRegisterDraft {
 
         private String phone;
-
-        private String encodedPassword;
 
         private String contactName;
 

--
Gitblit v1.7.1