Browse Source

重构代码

tsurumure 7 tháng trước cách đây
mục cha
commit
073c4aa50c

+ 92 - 92
src/main/java/com/backendsys/controller/Systems/SysAuthController.java

@@ -1,92 +1,92 @@
-package com.backendsys.controller.Systems;
-
-import com.backendsys.aspect.RateLimiting;
-import com.backendsys.modules.common.config.redis.utils.RedisUtil;
-import com.backendsys.modules.common.config.security.utils.TokenUtil;
-import com.backendsys.entity.System.SysUserDTO;
-import com.backendsys.mapper.System.SysUserMapper;
-import com.backendsys.utils.response.Result;
-import com.backendsys.service.System.SysAuthService;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.io.IOException;
-
-//@Tag(name = "登录管理")
-@RestController
-public class SysAuthController {
-
-    @Autowired
-    private StringRedisTemplate stringRedisTemplate;
-
-    @Autowired
-    private RedisUtil redisUtil;
-
-    @Autowired
-    private TokenUtil tokenUtil;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Value("${spring.config.name}")
-    private String configName;
-
-    @Autowired
-    private SysAuthService sysAuthService;
-
-//    /**
-//     * 获得图形验证码
-//     */
-//    @GetMapping("/api/system/auth/getCaptcha")
-//    public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
-//        sysAuthService.renderCaptcha(request, response);
-//    }
-
-    /** --------------------------------------------------------------------------------------- */
-//    /**
-//     * 登录 (用户名)
-//     */
-//    @PostMapping(value = "/api/system/auth/login")
-//    @RateLimiting(key = "systemLogin", limit = 5)
-//    public Result systemLogin(HttpServletRequest request, @Validated(SysUserDTO.Login.class) @RequestBody SysUserDTO sysUserDTO) {
-//        return Result.success(sysAuthService.login(request, sysUserDTO));
-//    }
-//    /**
-//     * 登录 (手机号码)
-//     */
-//    @PostMapping(value = "/api/system/auth/loginWithPhone")
-//    @RateLimiting(key = "systemLoginWithPhone", limit = 5)
-//    public Result systemLoginWithPhone(HttpServletRequest request, @Validated(SysUserDTO.LoginWithPhone.class) @RequestBody SysUserDTO sysUserDTO) {
-//        return Result.success(sysAuthService.loginWithPhone(request, sysUserDTO));
-//    }
-
-//    /**
-//     * 注册系统用户 (用户名 和 手机号码 必填)
-//     */
-//    @PostMapping("/api/public/system/user/registerUser")
-//    @RateLimiting(key = "registerUser", limit = 5)
-//    public Result registerUser(HttpServletRequest request, @Validated(SysUserDTO.Register.class) @RequestBody SysUserDTO sysUserDTO) {
-//        return Result.success(sysAuthService.registerUser(request, sysUserDTO), "注册成功");
-//    }
-
-    /**
-     * 忘记密码
-     */
-    @PostMapping("/api/public/system/user/forgotPassword")
-    public Result forgotPassword(@Validated(SysUserDTO.ForgotPassword.class) @RequestBody SysUserDTO sysUserDTO) {
-        return Result.success(sysAuthService.forgotPassword(sysUserDTO));
-    }
-
-    // 注意:如果使用 /api/system/auth/* 会被 SecurityConfig 过滤掉 Token (获取不到 Token)
-    @PostMapping(value = "/api/system/user/logout")
-    public Result systemLogout(HttpServletRequest request) {
-        return Result.success(sysAuthService.logout(request));
-    }
-
-}
+//package com.backendsys.controller.Systems;
+//
+//import com.backendsys.aspect.RateLimiting;
+//import com.backendsys.modules.common.config.redis.utils.RedisUtil;
+//import com.backendsys.modules.common.config.security.utils.TokenUtil;
+//import com.backendsys.entity.System.SysUserDTO;
+//import com.backendsys.mapper.System.SysUserMapper;
+//import com.backendsys.utils.response.Result;
+//import com.backendsys.service.System.SysAuthService;
+//
+//import jakarta.servlet.http.HttpServletRequest;
+//import jakarta.servlet.http.HttpServletResponse;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.data.redis.core.StringRedisTemplate;
+//import org.springframework.validation.annotation.Validated;
+//import org.springframework.web.bind.annotation.*;
+//
+//import java.io.IOException;
+//
+////@Tag(name = "登录管理")
+//@RestController
+//public class SysAuthController {
+//
+//    @Autowired
+//    private StringRedisTemplate stringRedisTemplate;
+//
+//    @Autowired
+//    private RedisUtil redisUtil;
+//
+//    @Autowired
+//    private TokenUtil tokenUtil;
+//
+//    @Autowired
+//    private SysUserMapper sysUserMapper;
+//
+//    @Value("${spring.config.name}")
+//    private String configName;
+//
+//    @Autowired
+//    private SysAuthService sysAuthService;
+//
+////    /**
+////     * 获得图形验证码
+////     */
+////    @GetMapping("/api/system/auth/getCaptcha")
+////    public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
+////        sysAuthService.renderCaptcha(request, response);
+////    }
+//
+//    /** --------------------------------------------------------------------------------------- */
+////    /**
+////     * 登录 (用户名)
+////     */
+////    @PostMapping(value = "/api/system/auth/login")
+////    @RateLimiting(key = "systemLogin", limit = 5)
+////    public Result systemLogin(HttpServletRequest request, @Validated(SysUserDTO.Login.class) @RequestBody SysUserDTO sysUserDTO) {
+////        return Result.success(sysAuthService.login(request, sysUserDTO));
+////    }
+////    /**
+////     * 登录 (手机号码)
+////     */
+////    @PostMapping(value = "/api/system/auth/loginWithPhone")
+////    @RateLimiting(key = "systemLoginWithPhone", limit = 5)
+////    public Result systemLoginWithPhone(HttpServletRequest request, @Validated(SysUserDTO.LoginWithPhone.class) @RequestBody SysUserDTO sysUserDTO) {
+////        return Result.success(sysAuthService.loginWithPhone(request, sysUserDTO));
+////    }
+//
+////    /**
+////     * 注册系统用户 (用户名 和 手机号码 必填)
+////     */
+////    @PostMapping("/api/public/system/user/registerUser")
+////    @RateLimiting(key = "registerUser", limit = 5)
+////    public Result registerUser(HttpServletRequest request, @Validated(SysUserDTO.Register.class) @RequestBody SysUserDTO sysUserDTO) {
+////        return Result.success(sysAuthService.registerUser(request, sysUserDTO), "注册成功");
+////    }
+//
+////    /**
+////     * 忘记密码
+////     */
+////    @PostMapping("/api/public/system/user/forgotPassword")
+////    public Result forgotPassword(@Validated(SysUserDTO.ForgotPassword.class) @RequestBody SysUserDTO sysUserDTO) {
+////        return Result.success(sysAuthService.forgotPassword(sysUserDTO));
+////    }
+//
+////    // 注意:如果使用 /api/system/auth/* 会被 SecurityConfig 过滤掉 Token (获取不到 Token)
+////    @PostMapping(value = "/api/system/user/logout")
+////    public Result systemLogout(HttpServletRequest request) {
+////        return Result.success(sysAuthService.logout(request));
+////    }
+//
+//}

+ 3 - 1
src/main/java/com/backendsys/modules/sms/controller/SmsController.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.sms.controller;
 
+import com.backendsys.modules.common.config.security.annotations.Anonymous;
 import com.backendsys.modules.common.utils.Result;
 import com.backendsys.modules.sms.entity.Sms;
 import com.backendsys.modules.sms.service.SmsService;
@@ -25,7 +26,8 @@ public class SmsController {
     /**
      * 发送短信
      */
-    @PostMapping("/api/public/system/sms/getSMS")
+    @Anonymous
+    @PostMapping("/api/system/sms/getSMS")
     public Result getSMS(@Validated(Sms.Send.class) @RequestBody Sms sms) throws TencentCloudSDKException {
         return Result.success().put("data", smsService.sendValidCode(sms));
     }

+ 8 - 9
src/main/java/com/backendsys/modules/system/controller/SysAuthV2Controller.java

@@ -45,9 +45,10 @@ public class SysAuthV2Controller {
     }
     // -------------------------------------------------------------------------------------------------
 
+    @Anonymous
     @Operation(summary = "获取手机号地区列表")
     @RateLimiting(key = "getMobileAreaCode")
-    @GetMapping("/api/public/system/getMobileAreaCode")
+    @GetMapping("/api/system/getMobileAreaCode")
     public Result getMobileAreaCode(@Validated SysMobileArea sysMobileArea) {
         return Result.success().put("data", sysAuthV2Service.getMobileAreaList(sysMobileArea));
     }
@@ -68,17 +69,15 @@ public class SysAuthV2Controller {
 
     @Anonymous
     @Operation(summary = "忘记密码")
-    @PostMapping("/api/v2/system/user/forgotPassword")
+    @PostMapping("/api/system/user/forgotPassword")
     public Result forgotPassword(@Validated(SysUserDTO.ForgotPassword.class) @RequestBody SysUserDTO sysUserDTO) {
         return Result.success().put("data", sysAuthV2Service.forgotPassword(sysUserDTO));
     }
-//
-//    // 注意:如果使用 /api/system/auth/* 会被 SecurityConfig 过滤掉 Token (获取不到 Token)
-//    @PostMapping(value = "/api/system/user/logout")
-//    public com.backendsys.utils.response.Result systemLogout(HttpServletRequest request) {
-//        return com.backendsys.utils.response.Result.success(sysAuthService.logout(request));
-//    }
-
 
+    @Operation(summary = "退出登录")
+    @PostMapping(value = "/api/system/user/logout")
+    public Result systemLogout() {
+        return Result.success().put("data", sysAuthV2Service.logout());
+    }
 
 }

+ 1 - 1
src/main/java/com/backendsys/modules/system/service/SysAuthV2Service.java

@@ -18,5 +18,5 @@ public interface SysAuthV2Service {
 
     Map<String, Object> register(SysUserDTO sysUserDTO);
     Map<String, Object> forgotPassword(SysUserDTO sysUserDTO);
-
+    Map<String, Object> logout();
 }

+ 39 - 5
src/main/java/com/backendsys/modules/system/service/impl/SysAuthV2ServiceImpl.java

@@ -324,19 +324,53 @@ public class SysAuthV2ServiceImpl implements SysAuthV2Service {
         return Map.of("user_id", registerEntity.getId());
     }
 
-
-
-
-
     /**
      * 忘记密码/重置密码
      */
     @Override
     public Map<String, Object> forgotPassword(SysUserDTO sysUserDTO) {
 
+        String phone = sysUserDTO.getPhone();
+        Integer phoneAreaCode = sysUserDTO.getPhone_area_code();
+        Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
 
+        // 判断短信验证码是否正确
+        String redisKey = "sms-forgotPassword-" + sysUserDTO.getPhone();
+        Integer smsCode = redisUtil.getCacheObject(redisKey);
+        if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
+            throw new CustException("短信验证码错误");
+        }
 
-        return Map.of("user_id", sysUserDTO.getId());
+        // [查询] 判断手机号是否存在
+        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SysUser::getPhone, phone).eq(SysUser::getPhone_area_code, phoneAreaCode);
+        SysUser sysUser = sysUserDao.selectOne(queryWrapper);
+        if (sysUser == null) throw new CustException("手机号码不存在");
+
+        // 密码二次加密
+        String password = sysUserDTO.getPassword();
+        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+        String encodedPassword = encoder.encode(password);
+        sysUser.setPassword(encodedPassword);
+
+        // 编辑密码
+        sysUserDao.updateById(sysUser);
+
+        // 更改成功,销毁短信验证码
+        redisUtil.delete(redisKey);
+
+        return Map.of("user_id", sysUser.getId());
+    }
+
+    /**
+     * 退出登录
+     */
+    public Map<String, Object> logout() {
+        Long user_id = httpRequestUtil.getUserId();
+        if (user_id != null) {
+            tokenUtil.deleteRedisLoginToken(null);
+        }
+        return Map.of("user_id", user_id);
     }
 
 

+ 17 - 17
src/main/java/com/backendsys/service/System/SysAuthService.java

@@ -1,17 +1,17 @@
-package com.backendsys.service.System;
-
-import com.backendsys.entity.System.SysUserDTO;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-
-import java.io.IOException;
-import java.util.Map;
-
-public interface SysAuthService {
-    void renderCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException;
-    Map<String, Object> login(HttpServletRequest request, SysUserDTO sysUserDTO);
-    Map<String, Object> loginWithPhone(HttpServletRequest request, SysUserDTO sysUserDTO);
-    Map<String, Object> registerUser(HttpServletRequest request, SysUserDTO sysUserDTO);
-    Map<String, Object> forgotPassword(SysUserDTO sysUserDTO);
-    Map<String, Object>  logout(HttpServletRequest request);
-}
+//package com.backendsys.service.System;
+//
+//import com.backendsys.entity.System.SysUserDTO;
+//import jakarta.servlet.http.HttpServletRequest;
+//import jakarta.servlet.http.HttpServletResponse;
+//
+//import java.io.IOException;
+//import java.util.Map;
+//
+//public interface SysAuthService {
+//    void renderCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException;
+//    Map<String, Object> login(HttpServletRequest request, SysUserDTO sysUserDTO);
+//    Map<String, Object> loginWithPhone(HttpServletRequest request, SysUserDTO sysUserDTO);
+//    Map<String, Object> registerUser(HttpServletRequest request, SysUserDTO sysUserDTO);
+//    Map<String, Object> forgotPassword(SysUserDTO sysUserDTO);
+//    Map<String, Object>  logout(HttpServletRequest request);
+//}

+ 454 - 454
src/main/java/com/backendsys/service/System/SysAuthServiceImpl.java

@@ -1,454 +1,454 @@
-package com.backendsys.service.System;
-
-import cn.hutool.json.JSONUtil;
-import com.backendsys.config.Kaptcha.KaptchaUtil;
-import com.backendsys.exception.CustException;
-import com.backendsys.modules.common.config.redis.utils.RedisUtil;
-import com.backendsys.modules.common.config.security.entity.SecurityUserInfo;
-import com.backendsys.modules.common.config.security.utils.TokenUtil;
-import com.backendsys.modules.system.dao.SysUserInfoDao;
-import com.backendsys.entity.System.SysUserDTO;
-import com.backendsys.service.SDKService.SDKTencent.SDKTencentSMSService;
-import com.backendsys.utils.CountUtil;
-import com.backendsys.utils.UserUtils;
-import com.backendsys.utils.response.ResultEnum;
-import com.backendsys.mapper.System.SysUserMapper;
-import com.backendsys.modules.common.config.security.utils.JwtUtil;
-import com.google.code.kaptcha.Producer;
-import jakarta.servlet.ServletOutputStream;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.redisson.api.RLock;
-import org.redisson.api.RedissonClient;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.core.env.Environment;
-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;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-
-@Service
-public class SysAuthServiceImpl implements SysAuthService {
-
-    @Autowired
-    private Environment env;
-    @Value("${tencent.sms.debug}")
-    private String SMS_DEBUG;
-    @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
-    private String REDIS_LOGIN_TOKEN_PREFIX;
-
-    @Autowired
-    private CountUtil countUtil;
-
-    @Lazy
-    @Autowired
-    RedissonClient redissonClient;
-
-    @Autowired
-    private RedisUtil redisUtil;
-
-    @Autowired
-    private TokenUtil tokenUtil;
-
-    @Autowired
-    private StringRedisTemplate stringRedisTemplate;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
-    @Autowired
-    private JwtUtil jwtUtil;
-
-    @Value("${TOKEN_DURATION_SYSTEM}")
-    private Long TOKEN_DURATION_SYSTEM;
-
-    @Value("${spring.config.name}")
-    private String configName;
-
-    @Value("${CAPTCHA_DURATION}")
-    private Long CAPTCHA_DURATION;
-
-    @Autowired
-    private Producer captchaProducer;
-
-    @Autowired
-    private SDKTencentSMSService sdkTencentSMSService;
-
-    @Autowired
-    private SysUserInfoDao sysUserInfoDao;
-
-    /**
-     * 渲染 图形验证码
-     */
-    public void renderCaptcha(HttpServletRequest request, HttpServletResponse response) throws RuntimeException, IOException {
-        byte[] captchaChallengeAsJpeg = null;
-        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
-        try {
-            String createText = captchaProducer.createText();
-            // 获得当前 (UA + IP) 生成的 Key
-            String captchaRedisKey = KaptchaUtil.getKaptchaKey(request);
-            // 保存 验证码字符串 到 redis 中
-            stringRedisTemplate.opsForValue().set(captchaRedisKey, createText, this.CAPTCHA_DURATION, TimeUnit.MILLISECONDS);
-            // 返回 BufferedImage 对象并转为 byte 写入到 byte 数组中
-            BufferedImage challenge = captchaProducer.createImage(createText);
-            ImageIO.write(challenge, "jpg", jpegOutputStream);
-            //
-        } catch (Exception e) {
-            response.sendError(HttpServletResponse.SC_NOT_FOUND);return;
-        }
-        // 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组
-        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
-        response.setHeader("Cache-Control", "no-store");
-        response.setHeader("Pragma", "no-cache");
-        response.setDateHeader("Expires", 0);
-        response.setContentType("image/jpeg");
-        ServletOutputStream responseOutputStream = response.getOutputStream();
-        responseOutputStream.write(captchaChallengeAsJpeg);
-        responseOutputStream.flush();
-        responseOutputStream.close();
-    }
-
-    // [Method] 判断图形验证码是否正确
-    private Boolean isCaptchaValid(String captcha, String captchaRedisKey) {
-        // 如果不是本地开发环境,则执行以下判断
-        String profileActive = env.getProperty("spring.profiles.active");
-        if (!("local".equals(profileActive))) {
-            // 判断验证码是否正确 (是否与Redis中的验证码匹配) (测试环境忽略)
-            String captchaRedisValue = stringRedisTemplate.opsForValue().get(captchaRedisKey);
-            if (captchaRedisValue == null || !captchaRedisValue.equalsIgnoreCase(captcha)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // [Method] 判断密码是否正确
-    private Boolean isUserPasswordValid(Map<String, Object> userDTO, String password) {
-        if (userDTO == null) return false;
-        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
-        return encoder.matches(password, (String) userDTO.get("password"));
-    }
-
-    /**
-     * [封装] 登录成功回调信息
-     */
-    private Map<String, Object> loginSuccess(HttpServletRequest request, SysUserDTO sysUserDTO) {
-
-        String uuid = String.valueOf(UUID.randomUUID());
-        Long userId = sysUserDTO.getUser_id();
-        Map<String, Object> sysUserDetail = sysUserMapper.queryUserDetail(userId);
-
-        // 判断用户是否已审核
-        Integer auditStatus = (Integer) sysUserDetail.get("audit_status");
-        if (auditStatus == 1) throw new CustException("请等待管理员审核");
-        if (auditStatus == -1) throw new CustException("审核未通过,请联系客服获取详细信息");
-
-        // [Redis] 删除旧 Redis Key
-        String old_uuid = (String) sysUserDetail.get("last_login_uuid");
-        if (old_uuid != null) stringRedisTemplate.delete("token:id:" + old_uuid);
-
-        // 3.判断用户 status 是否启用
-        Object status = sysUserDetail.get("status");
-        if (status != null && (Integer) status == -1) throw new CustException("该用户已被禁用");
-
-        // 4.格式化 modules: [{ id: 1, module_code: "xxx" }] 转为 ["1.x.x", "2.x.x"] (减少 Token 长度)
-        List<Map<String, Object>> roles = (List<Map<String, Object>>) sysUserDetail.get("roles");
-        if (roles != null) {
-            List<String> modules = UserUtils.extractModuleCodes(roles);
-            roles.forEach(role -> role.remove("module_ids"));
-            sysUserDetail.put("modules", modules);
-            sysUserDetail.put("roles", roles);
-        }
-
-        //// x.判断用户 del_flag 是否逻辑删除
-        //Object del_flag = sysUser.get("del_flag");
-        //if (del_flag != null && (Integer) del_flag == 1) {
-        //    return Result.error(ResultEnum.INVALID_CREDENTIALS.getCode(), "该用户不存在 (flag)");
-        //}
-
-        // 5.生成 Token 并存入 Redis
-        // 生成 Token 过期时间 (存入Token/带出Result返回值)
-        Boolean isRemember = sysUserDTO.getIs_remember();
-        Long tokenDuration = (isRemember != null && isRemember) ? TOKEN_DURATION_SYSTEM * 7 : TOKEN_DURATION_SYSTEM;
-        Date tokenExpiration = new Date((new Date()).getTime() + tokenDuration);
-        sysUserDetail.put("token_expiration", tokenExpiration);
-
-        // 生成 Token
-        sysUserDetail.put("last_login_uuid", uuid);
-
-//        Map<String, Object> userInfo = new LinkedHashMap<>(sysUserDetail);
-//        userInfo.remove("modules");
-//        String token = jwtUtil.createSystemToken(userInfo);
-
-        SecurityUserInfo securityUserInfo = JSONUtil.toBean(JSONUtil.parseObj(sysUserDetail), SecurityUserInfo.class);
-        String token = jwtUtil.createSystemJwtToken(securityUserInfo);
-
-        // 存入 Redis:Token、Token过期时间
-        String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + uuid;
-        stringRedisTemplate.opsForValue().set(tokenRedisKey, token, tokenDuration, TimeUnit.MILLISECONDS);
-
-        // 6.[更新] 用户最后登录时间、登录IP
-        SysUserDTO sysUserLastlogin = new SysUserDTO();
-        sysUserLastlogin.setUser_id(userId);
-        sysUserLastlogin.setLast_login_ip(request.getRemoteAddr());
-        sysUserLastlogin.setLast_login_uuid(uuid);
-        LocalDateTime now = LocalDateTime.now();
-        String formattedDateTime = now.toString();
-        sysUserLastlogin.setLast_login_time(formattedDateTime);
-        sysUserMapper.updateUserInfo(sysUserLastlogin);
-
-        // 7.[格式化] 将 Token 拼接到输出结果
-        Map<String, Object> result = new LinkedHashMap<>(sysUserDetail);
-        result.remove("del_flag");
-        result.put("token", token);
-
-        return result;
-    }
-
-    /**
-     * 登录 系统用户 (用户名)
-     * @param sysUserDTO(username, password, captcha)
-     * @return { token, sysUser }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> login(HttpServletRequest request, SysUserDTO sysUserDTO) {
-
-        String username = sysUserDTO.getUsername();
-        String password = sysUserDTO.getPassword();
-        String captcha = sysUserDTO.getCaptcha();
-
-        // 判断是否处于 5次的错误状态
-        countUtil.checkErrorStatus("login-error", username);
-
-        // [Redis] 验证码临时密钥
-        String captchaRedisKey = KaptchaUtil.getKaptchaKey(request);
-
-        // [Method] 判断验证码是否正确
-        if (!isCaptchaValid(captcha, captchaRedisKey)) {
-            stringRedisTemplate.delete(captchaRedisKey);
-            throw new CustException("验证码错误", ResultEnum.INVALID_CREDENTIALS.getCode());
-        }
-
-        // [Method] 判断 用户 是否存在 && 密码是否正确
-        Map<String, Object> sysUserSimple = sysUserMapper.queryUserByIdOrName(null, username, null, null);
-        if (sysUserSimple != null) {
-            sysUserDTO.setUser_id((Long) sysUserSimple.get("id"));
-        }
-        if (!(sysUserSimple != null && isUserPasswordValid(sysUserSimple, password))) {
-            stringRedisTemplate.delete(captchaRedisKey);
-            // 添加错误标记 (2分钟内错误5次,则出现提示)
-            countUtil.setErrorCount("login-error", username);
-            //
-            throw new CustException("用户名或密码错误", ResultEnum.INVALID_CREDENTIALS.getCode());
-        }
-
-        // 1.作废验证码密钥
-        stringRedisTemplate.delete(captchaRedisKey);
-
-        // [登录成功]
-        Map<String, Object> result = loginSuccess(request, sysUserDTO);
-
-        return result;
-    }
-
-    /**
-     * 登录 系统用户 (手机号码)
-     * @param sysUserDTO(phone, phone_valid_code)
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> loginWithPhone(HttpServletRequest request, SysUserDTO sysUserDTO) {
-
-        String phone = sysUserDTO.getPhone();
-        Integer phoneAreaCode = sysUserDTO.getPhone_area_code();
-        Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
-
-        // 判断是否处于 5次的错误状态
-        countUtil.checkErrorStatus("login-error", phone);
-
-        // 判断手机验证码是否正确
-        String redisKey = "sms-login-" + phone;
-        Integer smsCode = redisUtil.getCacheObject(redisKey);
-        System.out.println("smsCode: " + smsCode);
-
-        // 判断短信验证码是否错误
-        if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
-            // 添加错误标记 (2分钟内错误5次,则出现提示)
-            countUtil.setErrorCount("login-error", phone);
-            throw new CustException("短信验证码错误", ResultEnum.INVALID_CREDENTIALS.getCode());
-        }
-
-        // 判断手机号是否存在
-        Map<String, Object> sysUserSimple = sysUserMapper.queryUserByIdOrName(null, null, phone, phoneAreaCode);
-         if (sysUserSimple == null) {
-            throw new CustException("手机号码不存在", ResultEnum.INVALID_CREDENTIALS.getCode());
-        } else {
-            // 登录成功,销毁短信验证码
-            redisUtil.delete(redisKey);
-
-            // 登录成功回调
-            sysUserDTO.setUser_id((Long) sysUserSimple.get("id"));
-            Map<String, Object> result = loginSuccess(request, sysUserDTO);
-            return result;
-        }
-    }
-
-    /**
-     * 注册 系统用户
-     * @param sysUserDTO
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> registerUser(HttpServletRequest request, SysUserDTO sysUserDTO) {
-
-        //// 如果可以获得当前 token 的 id,那以后创建分布式锁时,可以按照 userId 来创建锁
-        //System.out.println("tokenService.getLoginUUID() = " + tokenService.getLoginUUID());
-
-        RLock lock = redissonClient.getLock("registerUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // -- 校验-----------------------------------------------------------------
-            // 判断图形验证码是否正确
-            String captcha = sysUserDTO.getCaptcha();
-            String captchaRedisKey = KaptchaUtil.getKaptchaKey(request);
-            if (!isCaptchaValid(captcha, captchaRedisKey)) {
-                stringRedisTemplate.delete(captchaRedisKey);
-                throw new CustException("图形验证码错误");
-            }
-            // 如果是用手机号注册,则还需判断短信验证码是否正确
-            if (sysUserDTO.getPhone() != null) {
-
-                Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
-
-                String redisKey = "sms-register-" + sysUserDTO.getPhone();
-                Integer smsCode = redisUtil.getCacheObject(redisKey);
-                // System.out.println("smsCode: " + smsCode);
-
-
-                if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
-                    throw new CustException("短信验证码错误");
-                }
-
-                // 判断手机号是否已注册
-                Map<String, Object> sysUserSimple1 = sysUserMapper.queryUserByIdOrName(null, null, sysUserDTO.getPhone(), sysUserDTO.getPhone_area_code());
-                if (sysUserSimple1 != null) {
-                    throw new CustException("手机号码已被注册");
-                }
-                // 判断用户名是否已注册
-                Map<String, Object> sysUserSimple2 = sysUserMapper.queryUserByIdOrName(null, sysUserDTO.getUsername(), null, null);
-                if (sysUserSimple2 != null) {
-                    throw new CustException("用户名已被注册");
-                }
-
-                // 判断密钥是否有效
-                String inviteCode = sysUserDTO.getInvite_code();
-                // .. 待做
-
-                // 注册成功,销毁短信验证码
-                redisUtil.delete(redisKey);
-                //
-            }
-
-            // -- 动作 -----------------------------------------------------------------
-
-            // 密码二次加密
-            String password = sysUserDTO.getPassword();
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
-            String encodedPassword = encoder.encode(password);
-            sysUserDTO.setPassword(encodedPassword);
-
-            // 注册时,默认使用 游客 2L 类型
-            LinkedHashMap<String, Object> role_id_obj = new LinkedHashMap<>();
-            role_id_obj.put("id", 2L);
-            List<LinkedHashMap<String, Object>> convertedList = new ArrayList<>();
-            convertedList.add(role_id_obj);
-
-            // 注册时,仅添加 Username、Password 字段值
-            SysUserDTO registerSysUserDTO = new SysUserDTO();
-            registerSysUserDTO.setUsername(sysUserDTO.getUsername());
-            registerSysUserDTO.setPhone(sysUserDTO.getPhone());
-            registerSysUserDTO.setPhone_valid_code(sysUserDTO.getPhone_valid_code());
-            registerSysUserDTO.setPassword(sysUserDTO.getPassword());
-            registerSysUserDTO.setRoles(convertedList);
-            registerSysUserDTO.setInvite_code(sysUserDTO.getInvite_code());
-
-            sysUserMapper.insertUser(registerSysUserDTO);
-            return Map.of("user_id", registerSysUserDTO.getId());
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-    /**
-     * 忘记密码
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> forgotPassword(SysUserDTO sysUserDTO) {
-        RLock lock = redissonClient.getLock("forgotPassword");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 1.判断短信验证码是否正确
-            Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
-
-            String redisKey = "sms-forgotPassword-" + sysUserDTO.getPhone();
-            Integer smsCode = redisUtil.getCacheObject(redisKey);
-//            System.out.println("smsCode: " + smsCode);
-
-            if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
-                throw new CustException("短信验证码错误");
-            }
-
-            // 2.判断手机号是否存在
-            Map<String, Object> sysUserSimple = sysUserMapper.queryUserByIdOrName(null, null, sysUserDTO.getPhone(), sysUserDTO.getPhone_area_code());
-            if (sysUserSimple == null) {
-                throw new CustException("手机号码不存在");
-            }
-
-            // 3.更改密码
-            SysUserDTO updateDTO = new SysUserDTO();
-            updateDTO.setUser_id((Long) sysUserSimple.get("id"));
-            // 密码二次加密
-            String password = sysUserDTO.getPassword();
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
-            String encodedPassword = encoder.encode(password);
-            updateDTO.setPassword(encodedPassword);
-
-            sysUserMapper.updateUserPassword(updateDTO);
-
-            // 更改成功,销毁短信验证码
-            redisUtil.delete(redisKey);
-
-            return Map.of("user_id", updateDTO.getUser_id());
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-    /**
-     * 退出登录 (系统用户)
-     */
-    @Override
-    public Map<String, Object> logout(HttpServletRequest request) {
-        String token = tokenUtil.getToken(request);
-        if (token != null && !token.isEmpty()) {
-            // 删除旧的登录缓存
-            tokenUtil.deleteRedisLoginToken(null);
-            return Map.of("message", "退出成功");
-        }
-        throw new CustException(ResultEnum.TOKEN_EMPTY_ERROR.getMessage(), ResultEnum.TOKEN_EMPTY_ERROR.getCode());
-    }
-
-}
+//package com.backendsys.service.System;
+//
+//import cn.hutool.json.JSONUtil;
+//import com.backendsys.config.Kaptcha.KaptchaUtil;
+//import com.backendsys.exception.CustException;
+//import com.backendsys.modules.common.config.redis.utils.RedisUtil;
+//import com.backendsys.modules.common.config.security.entity.SecurityUserInfo;
+//import com.backendsys.modules.common.config.security.utils.TokenUtil;
+//import com.backendsys.modules.system.dao.SysUserInfoDao;
+//import com.backendsys.entity.System.SysUserDTO;
+//import com.backendsys.service.SDKService.SDKTencent.SDKTencentSMSService;
+//import com.backendsys.utils.CountUtil;
+//import com.backendsys.utils.UserUtils;
+//import com.backendsys.utils.response.ResultEnum;
+//import com.backendsys.mapper.System.SysUserMapper;
+//import com.backendsys.modules.common.config.security.utils.JwtUtil;
+//import com.google.code.kaptcha.Producer;
+//import jakarta.servlet.ServletOutputStream;
+//import jakarta.servlet.http.HttpServletRequest;
+//import jakarta.servlet.http.HttpServletResponse;
+//import org.redisson.api.RLock;
+//import org.redisson.api.RedissonClient;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.context.annotation.Lazy;
+//import org.springframework.core.env.Environment;
+//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;
+//
+//import javax.imageio.ImageIO;
+//import java.awt.image.BufferedImage;
+//import java.io.ByteArrayOutputStream;
+//import java.io.IOException;
+//import java.time.LocalDateTime;
+//import java.util.*;
+//import java.util.concurrent.TimeUnit;
+//
+//@Service
+//public class SysAuthServiceImpl implements SysAuthService {
+//
+//    @Autowired
+//    private Environment env;
+//    @Value("${tencent.sms.debug}")
+//    private String SMS_DEBUG;
+//    @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
+//    private String REDIS_LOGIN_TOKEN_PREFIX;
+//
+//    @Autowired
+//    private CountUtil countUtil;
+//
+//    @Lazy
+//    @Autowired
+//    RedissonClient redissonClient;
+//
+//    @Autowired
+//    private RedisUtil redisUtil;
+//
+//    @Autowired
+//    private TokenUtil tokenUtil;
+//
+//    @Autowired
+//    private StringRedisTemplate stringRedisTemplate;
+//
+//    @Autowired
+//    private SysUserMapper sysUserMapper;
+//
+//    @Autowired
+//    private JwtUtil jwtUtil;
+//
+//    @Value("${TOKEN_DURATION_SYSTEM}")
+//    private Long TOKEN_DURATION_SYSTEM;
+//
+//    @Value("${spring.config.name}")
+//    private String configName;
+//
+//    @Value("${CAPTCHA_DURATION}")
+//    private Long CAPTCHA_DURATION;
+//
+//    @Autowired
+//    private Producer captchaProducer;
+//
+//    @Autowired
+//    private SDKTencentSMSService sdkTencentSMSService;
+//
+//    @Autowired
+//    private SysUserInfoDao sysUserInfoDao;
+//
+//    /**
+//     * 渲染 图形验证码
+//     */
+//    public void renderCaptcha(HttpServletRequest request, HttpServletResponse response) throws RuntimeException, IOException {
+//        byte[] captchaChallengeAsJpeg = null;
+//        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
+//        try {
+//            String createText = captchaProducer.createText();
+//            // 获得当前 (UA + IP) 生成的 Key
+//            String captchaRedisKey = KaptchaUtil.getKaptchaKey(request);
+//            // 保存 验证码字符串 到 redis 中
+//            stringRedisTemplate.opsForValue().set(captchaRedisKey, createText, this.CAPTCHA_DURATION, TimeUnit.MILLISECONDS);
+//            // 返回 BufferedImage 对象并转为 byte 写入到 byte 数组中
+//            BufferedImage challenge = captchaProducer.createImage(createText);
+//            ImageIO.write(challenge, "jpg", jpegOutputStream);
+//            //
+//        } catch (Exception e) {
+//            response.sendError(HttpServletResponse.SC_NOT_FOUND);return;
+//        }
+//        // 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组
+//        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
+//        response.setHeader("Cache-Control", "no-store");
+//        response.setHeader("Pragma", "no-cache");
+//        response.setDateHeader("Expires", 0);
+//        response.setContentType("image/jpeg");
+//        ServletOutputStream responseOutputStream = response.getOutputStream();
+//        responseOutputStream.write(captchaChallengeAsJpeg);
+//        responseOutputStream.flush();
+//        responseOutputStream.close();
+//    }
+//
+//    // [Method] 判断图形验证码是否正确
+//    private Boolean isCaptchaValid(String captcha, String captchaRedisKey) {
+//        // 如果不是本地开发环境,则执行以下判断
+//        String profileActive = env.getProperty("spring.profiles.active");
+//        if (!("local".equals(profileActive))) {
+//            // 判断验证码是否正确 (是否与Redis中的验证码匹配) (测试环境忽略)
+//            String captchaRedisValue = stringRedisTemplate.opsForValue().get(captchaRedisKey);
+//            if (captchaRedisValue == null || !captchaRedisValue.equalsIgnoreCase(captcha)) {
+//                return false;
+//            }
+//        }
+//        return true;
+//    }
+//
+//    // [Method] 判断密码是否正确
+//    private Boolean isUserPasswordValid(Map<String, Object> userDTO, String password) {
+//        if (userDTO == null) return false;
+//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+//        return encoder.matches(password, (String) userDTO.get("password"));
+//    }
+//
+//    /**
+//     * [封装] 登录成功回调信息
+//     */
+//    private Map<String, Object> loginSuccess(HttpServletRequest request, SysUserDTO sysUserDTO) {
+//
+//        String uuid = String.valueOf(UUID.randomUUID());
+//        Long userId = sysUserDTO.getUser_id();
+//        Map<String, Object> sysUserDetail = sysUserMapper.queryUserDetail(userId);
+//
+//        // 判断用户是否已审核
+//        Integer auditStatus = (Integer) sysUserDetail.get("audit_status");
+//        if (auditStatus == 1) throw new CustException("请等待管理员审核");
+//        if (auditStatus == -1) throw new CustException("审核未通过,请联系客服获取详细信息");
+//
+//        // [Redis] 删除旧 Redis Key
+//        String old_uuid = (String) sysUserDetail.get("last_login_uuid");
+//        if (old_uuid != null) stringRedisTemplate.delete("token:id:" + old_uuid);
+//
+//        // 3.判断用户 status 是否启用
+//        Object status = sysUserDetail.get("status");
+//        if (status != null && (Integer) status == -1) throw new CustException("该用户已被禁用");
+//
+//        // 4.格式化 modules: [{ id: 1, module_code: "xxx" }] 转为 ["1.x.x", "2.x.x"] (减少 Token 长度)
+//        List<Map<String, Object>> roles = (List<Map<String, Object>>) sysUserDetail.get("roles");
+//        if (roles != null) {
+//            List<String> modules = UserUtils.extractModuleCodes(roles);
+//            roles.forEach(role -> role.remove("module_ids"));
+//            sysUserDetail.put("modules", modules);
+//            sysUserDetail.put("roles", roles);
+//        }
+//
+//        //// x.判断用户 del_flag 是否逻辑删除
+//        //Object del_flag = sysUser.get("del_flag");
+//        //if (del_flag != null && (Integer) del_flag == 1) {
+//        //    return Result.error(ResultEnum.INVALID_CREDENTIALS.getCode(), "该用户不存在 (flag)");
+//        //}
+//
+//        // 5.生成 Token 并存入 Redis
+//        // 生成 Token 过期时间 (存入Token/带出Result返回值)
+//        Boolean isRemember = sysUserDTO.getIs_remember();
+//        Long tokenDuration = (isRemember != null && isRemember) ? TOKEN_DURATION_SYSTEM * 7 : TOKEN_DURATION_SYSTEM;
+//        Date tokenExpiration = new Date((new Date()).getTime() + tokenDuration);
+//        sysUserDetail.put("token_expiration", tokenExpiration);
+//
+//        // 生成 Token
+//        sysUserDetail.put("last_login_uuid", uuid);
+//
+////        Map<String, Object> userInfo = new LinkedHashMap<>(sysUserDetail);
+////        userInfo.remove("modules");
+////        String token = jwtUtil.createSystemToken(userInfo);
+//
+//        SecurityUserInfo securityUserInfo = JSONUtil.toBean(JSONUtil.parseObj(sysUserDetail), SecurityUserInfo.class);
+//        String token = jwtUtil.createSystemJwtToken(securityUserInfo);
+//
+//        // 存入 Redis:Token、Token过期时间
+//        String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + uuid;
+//        stringRedisTemplate.opsForValue().set(tokenRedisKey, token, tokenDuration, TimeUnit.MILLISECONDS);
+//
+//        // 6.[更新] 用户最后登录时间、登录IP
+//        SysUserDTO sysUserLastlogin = new SysUserDTO();
+//        sysUserLastlogin.setUser_id(userId);
+//        sysUserLastlogin.setLast_login_ip(request.getRemoteAddr());
+//        sysUserLastlogin.setLast_login_uuid(uuid);
+//        LocalDateTime now = LocalDateTime.now();
+//        String formattedDateTime = now.toString();
+//        sysUserLastlogin.setLast_login_time(formattedDateTime);
+//        sysUserMapper.updateUserInfo(sysUserLastlogin);
+//
+//        // 7.[格式化] 将 Token 拼接到输出结果
+//        Map<String, Object> result = new LinkedHashMap<>(sysUserDetail);
+//        result.remove("del_flag");
+//        result.put("token", token);
+//
+//        return result;
+//    }
+//
+//    /**
+//     * 登录 系统用户 (用户名)
+//     * @param sysUserDTO(username, password, captcha)
+//     * @return { token, sysUser }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> login(HttpServletRequest request, SysUserDTO sysUserDTO) {
+//
+//        String username = sysUserDTO.getUsername();
+//        String password = sysUserDTO.getPassword();
+//        String captcha = sysUserDTO.getCaptcha();
+//
+//        // 判断是否处于 5次的错误状态
+//        countUtil.checkErrorStatus("login-error", username);
+//
+//        // [Redis] 验证码临时密钥
+//        String captchaRedisKey = KaptchaUtil.getKaptchaKey(request);
+//
+//        // [Method] 判断验证码是否正确
+//        if (!isCaptchaValid(captcha, captchaRedisKey)) {
+//            stringRedisTemplate.delete(captchaRedisKey);
+//            throw new CustException("验证码错误", ResultEnum.INVALID_CREDENTIALS.getCode());
+//        }
+//
+//        // [Method] 判断 用户 是否存在 && 密码是否正确
+//        Map<String, Object> sysUserSimple = sysUserMapper.queryUserByIdOrName(null, username, null, null);
+//        if (sysUserSimple != null) {
+//            sysUserDTO.setUser_id((Long) sysUserSimple.get("id"));
+//        }
+//        if (!(sysUserSimple != null && isUserPasswordValid(sysUserSimple, password))) {
+//            stringRedisTemplate.delete(captchaRedisKey);
+//            // 添加错误标记 (2分钟内错误5次,则出现提示)
+//            countUtil.setErrorCount("login-error", username);
+//            //
+//            throw new CustException("用户名或密码错误", ResultEnum.INVALID_CREDENTIALS.getCode());
+//        }
+//
+//        // 1.作废验证码密钥
+//        stringRedisTemplate.delete(captchaRedisKey);
+//
+//        // [登录成功]
+//        Map<String, Object> result = loginSuccess(request, sysUserDTO);
+//
+//        return result;
+//    }
+//
+//    /**
+//     * 登录 系统用户 (手机号码)
+//     * @param sysUserDTO(phone, phone_valid_code)
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> loginWithPhone(HttpServletRequest request, SysUserDTO sysUserDTO) {
+//
+//        String phone = sysUserDTO.getPhone();
+//        Integer phoneAreaCode = sysUserDTO.getPhone_area_code();
+//        Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
+//
+//        // 判断是否处于 5次的错误状态
+//        countUtil.checkErrorStatus("login-error", phone);
+//
+//        // 判断手机验证码是否正确
+//        String redisKey = "sms-login-" + phone;
+//        Integer smsCode = redisUtil.getCacheObject(redisKey);
+//        System.out.println("smsCode: " + smsCode);
+//
+//        // 判断短信验证码是否错误
+//        if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
+//            // 添加错误标记 (2分钟内错误5次,则出现提示)
+//            countUtil.setErrorCount("login-error", phone);
+//            throw new CustException("短信验证码错误", ResultEnum.INVALID_CREDENTIALS.getCode());
+//        }
+//
+//        // 判断手机号是否存在
+//        Map<String, Object> sysUserSimple = sysUserMapper.queryUserByIdOrName(null, null, phone, phoneAreaCode);
+//         if (sysUserSimple == null) {
+//            throw new CustException("手机号码不存在", ResultEnum.INVALID_CREDENTIALS.getCode());
+//        } else {
+//            // 登录成功,销毁短信验证码
+//            redisUtil.delete(redisKey);
+//
+//            // 登录成功回调
+//            sysUserDTO.setUser_id((Long) sysUserSimple.get("id"));
+//            Map<String, Object> result = loginSuccess(request, sysUserDTO);
+//            return result;
+//        }
+//    }
+//
+//    /**
+//     * 注册 系统用户
+//     * @param sysUserDTO
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> registerUser(HttpServletRequest request, SysUserDTO sysUserDTO) {
+//
+//        //// 如果可以获得当前 token 的 id,那以后创建分布式锁时,可以按照 userId 来创建锁
+//        //System.out.println("tokenService.getLoginUUID() = " + tokenService.getLoginUUID());
+//
+//        RLock lock = redissonClient.getLock("registerUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // -- 校验-----------------------------------------------------------------
+//            // 判断图形验证码是否正确
+//            String captcha = sysUserDTO.getCaptcha();
+//            String captchaRedisKey = KaptchaUtil.getKaptchaKey(request);
+//            if (!isCaptchaValid(captcha, captchaRedisKey)) {
+//                stringRedisTemplate.delete(captchaRedisKey);
+//                throw new CustException("图形验证码错误");
+//            }
+//            // 如果是用手机号注册,则还需判断短信验证码是否正确
+//            if (sysUserDTO.getPhone() != null) {
+//
+//                Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
+//
+//                String redisKey = "sms-register-" + sysUserDTO.getPhone();
+//                Integer smsCode = redisUtil.getCacheObject(redisKey);
+//                // System.out.println("smsCode: " + smsCode);
+//
+//
+//                if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
+//                    throw new CustException("短信验证码错误");
+//                }
+//
+//                // 判断手机号是否已注册
+//                Map<String, Object> sysUserSimple1 = sysUserMapper.queryUserByIdOrName(null, null, sysUserDTO.getPhone(), sysUserDTO.getPhone_area_code());
+//                if (sysUserSimple1 != null) {
+//                    throw new CustException("手机号码已被注册");
+//                }
+//                // 判断用户名是否已注册
+//                Map<String, Object> sysUserSimple2 = sysUserMapper.queryUserByIdOrName(null, sysUserDTO.getUsername(), null, null);
+//                if (sysUserSimple2 != null) {
+//                    throw new CustException("用户名已被注册");
+//                }
+//
+//                // 判断密钥是否有效
+//                String inviteCode = sysUserDTO.getInvite_code();
+//                // .. 待做
+//
+//                // 注册成功,销毁短信验证码
+//                redisUtil.delete(redisKey);
+//                //
+//            }
+//
+//            // -- 动作 -----------------------------------------------------------------
+//
+//            // 密码二次加密
+//            String password = sysUserDTO.getPassword();
+//            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+//            String encodedPassword = encoder.encode(password);
+//            sysUserDTO.setPassword(encodedPassword);
+//
+//            // 注册时,默认使用 游客 2L 类型
+//            LinkedHashMap<String, Object> role_id_obj = new LinkedHashMap<>();
+//            role_id_obj.put("id", 2L);
+//            List<LinkedHashMap<String, Object>> convertedList = new ArrayList<>();
+//            convertedList.add(role_id_obj);
+//
+//            // 注册时,仅添加 Username、Password 字段值
+//            SysUserDTO registerSysUserDTO = new SysUserDTO();
+//            registerSysUserDTO.setUsername(sysUserDTO.getUsername());
+//            registerSysUserDTO.setPhone(sysUserDTO.getPhone());
+//            registerSysUserDTO.setPhone_valid_code(sysUserDTO.getPhone_valid_code());
+//            registerSysUserDTO.setPassword(sysUserDTO.getPassword());
+//            registerSysUserDTO.setRoles(convertedList);
+//            registerSysUserDTO.setInvite_code(sysUserDTO.getInvite_code());
+//
+//            sysUserMapper.insertUser(registerSysUserDTO);
+//            return Map.of("user_id", registerSysUserDTO.getId());
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//    /**
+//     * 忘记密码
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> forgotPassword(SysUserDTO sysUserDTO) {
+//        RLock lock = redissonClient.getLock("forgotPassword");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 1.判断短信验证码是否正确
+//            Integer phoneValidCode = sysUserDTO.getPhone_valid_code();
+//
+//            String redisKey = "sms-forgotPassword-" + sysUserDTO.getPhone();
+//            Integer smsCode = redisUtil.getCacheObject(redisKey);
+////            System.out.println("smsCode: " + smsCode);
+//
+//            if ("false".equals(SMS_DEBUG) && (smsCode == null || !smsCode.equals(phoneValidCode))) {
+//                throw new CustException("短信验证码错误");
+//            }
+//
+//            // 2.判断手机号是否存在
+//            Map<String, Object> sysUserSimple = sysUserMapper.queryUserByIdOrName(null, null, sysUserDTO.getPhone(), sysUserDTO.getPhone_area_code());
+//            if (sysUserSimple == null) {
+//                throw new CustException("手机号码不存在");
+//            }
+//
+//            // 3.更改密码
+//            SysUserDTO updateDTO = new SysUserDTO();
+//            updateDTO.setUser_id((Long) sysUserSimple.get("id"));
+//            // 密码二次加密
+//            String password = sysUserDTO.getPassword();
+//            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+//            String encodedPassword = encoder.encode(password);
+//            updateDTO.setPassword(encodedPassword);
+//
+//            sysUserMapper.updateUserPassword(updateDTO);
+//
+//            // 更改成功,销毁短信验证码
+//            redisUtil.delete(redisKey);
+//
+//            return Map.of("user_id", updateDTO.getUser_id());
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//    /**
+//     * 退出登录 (系统用户)
+//     */
+//    @Override
+//    public Map<String, Object> logout(HttpServletRequest request) {
+//        String token = tokenUtil.getToken(request);
+//        if (token != null && !token.isEmpty()) {
+//            // 删除旧的登录缓存
+//            tokenUtil.deleteRedisLoginToken(null);
+//            return Map.of("message", "退出成功");
+//        }
+//        throw new CustException(ResultEnum.TOKEN_EMPTY_ERROR.getMessage(), ResultEnum.TOKEN_EMPTY_ERROR.getCode());
+//    }
+//
+//}

+ 11 - 11
src/main/java/com/backendsys/service/System/SysUserService.java

@@ -7,18 +7,18 @@ import java.util.List;
 import java.util.Map;
 
 public interface SysUserService {
-    Map<String, Object> queryUserList(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO);
-    List<Map<String, Object>> queryUserWithLogined(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO);
+//    Map<String, Object> queryUserList(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO);
+//    List<Map<String, Object>> queryUserWithLogined(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO);
     Map<String, Object> queryUserById(Long user_id);
-    Map<String, Object> insertUser(SysUserDTO sysUserDTO);
+//    Map<String, Object> insertUser(SysUserDTO sysUserDTO);
     Map<String, Object> updateUserInfo(SysUserDTO sysUserDTO);
 
-    Map<String, Object> auditUser(SysUserDTO sysUserDTO);
-    Map<String, Object> deleteUser(Long id);
-    Map<String, Object> deleteUserBatch(List<Long> ids);
-    Map<String, Object> deactivateUser(Long id);
-    Map<String, Object> kickUser(Long id);
-    Map<String, Object> queryUserPassword(Long id);
-    Map<String, Object> updateUserPasswordSelf(SysUserDTO sysUserDTO);
-    Map<String, Object> resetUserPassword(SysUserDTO sysUserDTO) throws NoSuchAlgorithmException;
+//    Map<String, Object> auditUser(SysUserDTO sysUserDTO);
+//    Map<String, Object> deleteUser(Long id);
+//    Map<String, Object> deleteUserBatch(List<Long> ids);
+//    Map<String, Object> deactivateUser(Long id);
+//    Map<String, Object> kickUser(Long id);
+//    Map<String, Object> queryUserPassword(Long id);
+//    Map<String, Object> updateUserPasswordSelf(SysUserDTO sysUserDTO);
+//    Map<String, Object> resetUserPassword(SysUserDTO sysUserDTO) throws NoSuchAlgorithmException;
 }

+ 268 - 268
src/main/java/com/backendsys/service/System/SysUserServiceImpl.java

@@ -37,40 +37,40 @@ public class SysUserServiceImpl implements SysUserService {
     @Autowired
     private SysUserMapper sysUserMapper;
 
-    /**
-     * 查询 系统用户列表
-     */
-    @Override
-    public Map<String, Object> queryUserList(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO) {
-        // 分页查询
-        if (pageNum != null && pageSize != null) {
-            PageHelper.startPage(pageNum, pageSize);
-        }
-        // 分页输出 (自定义)
-        List<Map<String, Object>> list = sysUserMapper.queryUserList(sysUserDTO);
-        PageInfoResult pageInfoResult = new PageInfoResult(list);
-        return pageInfoResult.toMap();
-    }
-
-    /**
-     * 查询 系统用户列表 (在线)
-     */
-    @Override
-    public List<Map<String, Object>> queryUserWithLogined(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO) {
-        // 分页查询
-        if (pageNum != null && pageSize != null) {
-            PageHelper.startPage(pageNum, pageSize);
-        }
-
-        // 获得用户最后登录的UUID
-        Set redisKeys = redisTemplate.keys("token:*");
-        // 获得UUID数组
-        Set last_login_uuids = (Set) redisKeys.stream().map(
-            e -> String.valueOf(e).replace(REDIS_LOGIN_TOKEN_PREFIX, "")
-        ).collect(Collectors.toSet());
-
-        return sysUserMapper.queryUserWithLogined(last_login_uuids);
-    }
+//    /**
+//     * 查询 系统用户列表
+//     */
+//    @Override
+//    public Map<String, Object> queryUserList(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO) {
+//        // 分页查询
+//        if (pageNum != null && pageSize != null) {
+//            PageHelper.startPage(pageNum, pageSize);
+//        }
+//        // 分页输出 (自定义)
+//        List<Map<String, Object>> list = sysUserMapper.queryUserList(sysUserDTO);
+//        PageInfoResult pageInfoResult = new PageInfoResult(list);
+//        return pageInfoResult.toMap();
+//    }
+//
+//    /**
+//     * 查询 系统用户列表 (在线)
+//     */
+//    @Override
+//    public List<Map<String, Object>> queryUserWithLogined(Integer pageNum, Integer pageSize, SysUserDTO sysUserDTO) {
+//        // 分页查询
+//        if (pageNum != null && pageSize != null) {
+//            PageHelper.startPage(pageNum, pageSize);
+//        }
+//
+//        // 获得用户最后登录的UUID
+//        Set redisKeys = redisTemplate.keys("token:*");
+//        // 获得UUID数组
+//        Set last_login_uuids = (Set) redisKeys.stream().map(
+//            e -> String.valueOf(e).replace(REDIS_LOGIN_TOKEN_PREFIX, "")
+//        ).collect(Collectors.toSet());
+//
+//        return sysUserMapper.queryUserWithLogined(last_login_uuids);
+//    }
 
     /**
      * 查询 系统用户详情
@@ -99,45 +99,45 @@ public class SysUserServiceImpl implements SysUserService {
 
     
 
-    /**
-     * 创建 系统用户
-     * @param sysUserDTO
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> insertUser(SysUserDTO sysUserDTO) {
-
-        //// 如果可以获得当前 token 的 id,那以后创建分布式锁时,可以按照 userId 来创建锁
-        //System.out.println("tokenService.getLoginUUID() = " + tokenService.getLoginUUID());
-
-        RLock lock = redissonClient.getLock("insertUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 密码二次加密
-            String password = sysUserDTO.getPassword();
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
-            String encodedPassword = encoder.encode(password);
-            sysUserDTO.setPassword(encodedPassword);
-
-            // 获取参数,并将 [1,2] 转换为 [{ id: 1 }, { id: 2 }]
-            List<Long> role_id = sysUserDTO.getRole_id();
-            List<LinkedHashMap<String,Object>> convertedList = role_id.stream()
-                .map(id -> {
-                    LinkedHashMap<String,Object> map = new LinkedHashMap<>();
-                    map.put("id", id);
-                    return map;
-                })
-                .collect(Collectors.toList());
-            sysUserDTO.setRoles(convertedList);
-            // ------------------------------------------------------
-
-            sysUserMapper.insertUser(sysUserDTO);
-            return Map.of("user_id", sysUserDTO.getId());
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
+//    /**
+//     * 创建 系统用户
+//     * @param sysUserDTO
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> insertUser(SysUserDTO sysUserDTO) {
+//
+//        //// 如果可以获得当前 token 的 id,那以后创建分布式锁时,可以按照 userId 来创建锁
+//        //System.out.println("tokenService.getLoginUUID() = " + tokenService.getLoginUUID());
+//
+//        RLock lock = redissonClient.getLock("insertUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 密码二次加密
+//            String password = sysUserDTO.getPassword();
+//            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+//            String encodedPassword = encoder.encode(password);
+//            sysUserDTO.setPassword(encodedPassword);
+//
+//            // 获取参数,并将 [1,2] 转换为 [{ id: 1 }, { id: 2 }]
+//            List<Long> role_id = sysUserDTO.getRole_id();
+//            List<LinkedHashMap<String,Object>> convertedList = role_id.stream()
+//                .map(id -> {
+//                    LinkedHashMap<String,Object> map = new LinkedHashMap<>();
+//                    map.put("id", id);
+//                    return map;
+//                })
+//                .collect(Collectors.toList());
+//            sysUserDTO.setRoles(convertedList);
+//            // ------------------------------------------------------
+//
+//            sysUserMapper.insertUser(sysUserDTO);
+//            return Map.of("user_id", sysUserDTO.getId());
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
 
     /**
      * 更新 系统用户信息
@@ -180,200 +180,200 @@ public class SysUserServiceImpl implements SysUserService {
         } finally { lock.unlock(); }
     }
 
-    /**
-     * 审核 系统用户
-     * @param sysUserDTO
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> auditUser(SysUserDTO sysUserDTO) {
-        RLock lock = redissonClient.getLock("auditUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            sysUserMapper.auditUser(sysUserDTO);
-            return Map.of("user_id", sysUserDTO.getUser_id());
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-
-    /**
-     * 删除 系统用户 (物理删除)
-     * @param id
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> deleteUser(Long id) {
-        RLock lock = redissonClient.getLock("deleteUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 删除前,清除登录状态
-            Map<String, Object> sysUser = sysUserMapper.queryUserDetail(id);
-//            String last_login_uuid = (String) sysUser.get("last_login_uuid");
-            String last_login_uuid = Convert.toStr(sysUser.get("last_login_uuid"));
-            redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
-
-            sysUserMapper.deleteUser(id);
-            return Map.of("user_id", id);
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-    /**
-     * 删除 系统用户 (批量)
-     * @param ids
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> deleteUserBatch(List<Long> ids) {
-        RLock lock = redissonClient.getLock("deleteUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 删除前,清除登录状态 (这里的查询需要优化一下,使用批量查询)
-            List<Map<String, Object>> uuids = sysUserMapper.queryUserUUIDSByIds(ids);
-            for (Map<String, Object> uuidMap : uuids) {
-                if (uuidMap != null && uuidMap.containsKey("last_login_uuid")) {
-                    String last_login_uuid = (String) uuidMap.get("last_login_uuid");
-                    if (last_login_uuid != null && !last_login_uuid.isEmpty()) {
-                        // 这里忽略清除 userInfo 的 last_login_uuid 字段,因为要删除了
-                        redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
-                    }
-                }
-            }
-
-            sysUserMapper.deleteUserBatch(ids);
-            return Map.of("user_ids", ids);
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-
-    /**
-     * 删除 系统用户 (逻辑删除)
-     * @param id
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> deactivateUser(Long id) {
-        RLock lock = redissonClient.getLock("deactivateUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 删除前,清除登录状态
-            Map<String, Object> sysUser = sysUserMapper.queryUserDetail(id);
-//            String last_login_uuid = (String) sysUser.get("last_login_uuid");
-            String last_login_uuid = Convert.toStr(sysUser.get("last_login_uuid"));
-            redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
-
-            sysUserMapper.deactivateUser(id);
-            return Map.of("user_id", id);
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-    /**
-     * 查询用户密码
-     * @param id
-     * @return
-     */
-    @Override
-    public Map<String, Object> queryUserPassword(Long id) {
-        return sysUserMapper.queryUserPassword(id);
-    }
-
-    /**
-     * 更新 系统用户密码 (自身)
-     * @param sysUserDTO
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> updateUserPasswordSelf(SysUserDTO sysUserDTO) {
-        RLock lock = redissonClient.getLock("updateUserPasswordSelf");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 密码二次加密
-            String password = sysUserDTO.getPassword();
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
-            String encodedPassword = encoder.encode(password);
-            sysUserDTO.setPassword(encodedPassword);
-            //
-            sysUserMapper.updateUserPassword(sysUserDTO);
-            return Map.of("user_id", sysUserDTO.getUser_id());
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-    /**
-     * 更新 重置用户密码 (超级管理员)
-     * @param sysUserDTO
-     * @return { user_id }
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> resetUserPassword(SysUserDTO sysUserDTO) throws NoSuchAlgorithmException {
-        RLock lock = redissonClient.getLock("resetUserPassword");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            // 生成一个六位的随机数密码
-            String uuid = UUID.randomUUID().toString().replace("-", "");
-            String password = uuid.substring(0, 6);
-            // MD5加密
-            String md5Password = MD5Util.encrypt(password);
-            // 加盐加密
-            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
-            String encodedPassword = encoder.encode(md5Password);
-            sysUserDTO.setPassword(encodedPassword);
-            //
-            sysUserMapper.updateUserPassword(sysUserDTO);
-            Map<String, Object> response = new LinkedHashMap<>();
-            response.put("user_id", sysUserDTO.getUser_id());
-            response.put("plain_password", password);
-            return response;
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
-
-    /**
-     * 踢出用户 (下线)
-     */
-    @Override
-    @Transactional
-    public Map<String, Object> kickUser(Long user_id) {
-        RLock lock = redissonClient.getLock("kickUser");
-        try { lock.tryLock(3, TimeUnit.SECONDS);
-
-            Map<String, Object> sysUser = sysUserMapper.queryUserDetail(user_id);
-            if (sysUser.isEmpty()) { return null; }
-
-            // 清除 info 表中的 last_login_uuid 信息 (注意:至少要有一个值,不能全部是 null,否则报错)
-            SysUserDTO sysUserDTO = new SysUserDTO();
-            sysUserDTO.setUser_id(user_id);
-            // sysUserDTO.setNickname((String) sysUser.get("nickname"));
-            sysUserDTO.setLast_login_uuid("");
-            sysUserMapper.updateUserInfo(sysUserDTO);
-
-            // 清除 Redis 登录信息
-//            String last_login_uuid = (String) sysUser.get("last_login_uuid");
-            String last_login_uuid = Convert.toStr(sysUser.get("last_login_uuid"));
-            if (!last_login_uuid.isEmpty()) {
-                redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
-                return Map.of("user_id", user_id);
-            } else {
-                return Map.of("user_id", null);
-            }
-
-        } catch (InterruptedException e) { throw new RuntimeException(e);
-        } finally { lock.unlock(); }
-    }
+//    /**
+//     * 审核 系统用户
+//     * @param sysUserDTO
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> auditUser(SysUserDTO sysUserDTO) {
+//        RLock lock = redissonClient.getLock("auditUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            sysUserMapper.auditUser(sysUserDTO);
+//            return Map.of("user_id", sysUserDTO.getUser_id());
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//
+//    /**
+//     * 删除 系统用户 (物理删除)
+//     * @param id
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> deleteUser(Long id) {
+//        RLock lock = redissonClient.getLock("deleteUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 删除前,清除登录状态
+//            Map<String, Object> sysUser = sysUserMapper.queryUserDetail(id);
+////            String last_login_uuid = (String) sysUser.get("last_login_uuid");
+//            String last_login_uuid = Convert.toStr(sysUser.get("last_login_uuid"));
+//            redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
+//
+//            sysUserMapper.deleteUser(id);
+//            return Map.of("user_id", id);
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//    /**
+//     * 删除 系统用户 (批量)
+//     * @param ids
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> deleteUserBatch(List<Long> ids) {
+//        RLock lock = redissonClient.getLock("deleteUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 删除前,清除登录状态 (这里的查询需要优化一下,使用批量查询)
+//            List<Map<String, Object>> uuids = sysUserMapper.queryUserUUIDSByIds(ids);
+//            for (Map<String, Object> uuidMap : uuids) {
+//                if (uuidMap != null && uuidMap.containsKey("last_login_uuid")) {
+//                    String last_login_uuid = (String) uuidMap.get("last_login_uuid");
+//                    if (last_login_uuid != null && !last_login_uuid.isEmpty()) {
+//                        // 这里忽略清除 userInfo 的 last_login_uuid 字段,因为要删除了
+//                        redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
+//                    }
+//                }
+//            }
+//
+//            sysUserMapper.deleteUserBatch(ids);
+//            return Map.of("user_ids", ids);
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//
+//    /**
+//     * 删除 系统用户 (逻辑删除)
+//     * @param id
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> deactivateUser(Long id) {
+//        RLock lock = redissonClient.getLock("deactivateUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 删除前,清除登录状态
+//            Map<String, Object> sysUser = sysUserMapper.queryUserDetail(id);
+////            String last_login_uuid = (String) sysUser.get("last_login_uuid");
+//            String last_login_uuid = Convert.toStr(sysUser.get("last_login_uuid"));
+//            redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
+//
+//            sysUserMapper.deactivateUser(id);
+//            return Map.of("user_id", id);
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//    /**
+//     * 查询用户密码
+//     * @param id
+//     * @return
+//     */
+//    @Override
+//    public Map<String, Object> queryUserPassword(Long id) {
+//        return sysUserMapper.queryUserPassword(id);
+//    }
+//
+//    /**
+//     * 更新 系统用户密码 (自身)
+//     * @param sysUserDTO
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> updateUserPasswordSelf(SysUserDTO sysUserDTO) {
+//        RLock lock = redissonClient.getLock("updateUserPasswordSelf");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 密码二次加密
+//            String password = sysUserDTO.getPassword();
+//            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+//            String encodedPassword = encoder.encode(password);
+//            sysUserDTO.setPassword(encodedPassword);
+//            //
+//            sysUserMapper.updateUserPassword(sysUserDTO);
+//            return Map.of("user_id", sysUserDTO.getUser_id());
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//    /**
+//     * 更新 重置用户密码 (超级管理员)
+//     * @param sysUserDTO
+//     * @return { user_id }
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> resetUserPassword(SysUserDTO sysUserDTO) throws NoSuchAlgorithmException {
+//        RLock lock = redissonClient.getLock("resetUserPassword");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            // 生成一个六位的随机数密码
+//            String uuid = UUID.randomUUID().toString().replace("-", "");
+//            String password = uuid.substring(0, 6);
+//            // MD5加密
+//            String md5Password = MD5Util.encrypt(password);
+//            // 加盐加密
+//            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+//            String encodedPassword = encoder.encode(md5Password);
+//            sysUserDTO.setPassword(encodedPassword);
+//            //
+//            sysUserMapper.updateUserPassword(sysUserDTO);
+//            Map<String, Object> response = new LinkedHashMap<>();
+//            response.put("user_id", sysUserDTO.getUser_id());
+//            response.put("plain_password", password);
+//            return response;
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
+//
+//    /**
+//     * 踢出用户 (下线)
+//     */
+//    @Override
+//    @Transactional
+//    public Map<String, Object> kickUser(Long user_id) {
+//        RLock lock = redissonClient.getLock("kickUser");
+//        try { lock.tryLock(3, TimeUnit.SECONDS);
+//
+//            Map<String, Object> sysUser = sysUserMapper.queryUserDetail(user_id);
+//            if (sysUser.isEmpty()) { return null; }
+//
+//            // 清除 info 表中的 last_login_uuid 信息 (注意:至少要有一个值,不能全部是 null,否则报错)
+//            SysUserDTO sysUserDTO = new SysUserDTO();
+//            sysUserDTO.setUser_id(user_id);
+//            // sysUserDTO.setNickname((String) sysUser.get("nickname"));
+//            sysUserDTO.setLast_login_uuid("");
+//            sysUserMapper.updateUserInfo(sysUserDTO);
+//
+//            // 清除 Redis 登录信息
+////            String last_login_uuid = (String) sysUser.get("last_login_uuid");
+//            String last_login_uuid = Convert.toStr(sysUser.get("last_login_uuid"));
+//            if (!last_login_uuid.isEmpty()) {
+//                redisTemplate.delete(REDIS_LOGIN_TOKEN_PREFIX + last_login_uuid);
+//                return Map.of("user_id", user_id);
+//            } else {
+//                return Map.of("user_id", null);
+//            }
+//
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
+//    }
 
 }