Bladeren bron

Merge branch 'dev-yhq'

tsurumure 2 weken geleden
bovenliggende
commit
49ae2bb01d

+ 11 - 0
src/main/java/com/backendsys/modules/TestController.java

@@ -8,6 +8,7 @@ import cn.hutool.json.JSONUtil;
 import com.backendsys.aspect.RateLimiting;
 import com.backendsys.aspect.QueuingPoll;
 import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
+import com.backendsys.modules.common.config.security.utils.JwtUtil;
 import com.backendsys.modules.common.utils.Result;
 import com.backendsys.modules.sdk.baidu.yunapp.entity.ExecuteScriptParams;
 import com.backendsys.modules.sdk.baidu.yunapp.service.YunappService;
@@ -30,6 +31,7 @@ import com.tencentcloudapi.common.Credential;
 //import io.github.pigmesh.ai.deepseek.core.chat.ChatCompletionResponse;
 import com.volcengine.service.visual.IVisualService;
 import com.volcengine.service.visual.impl.VisualServiceImpl;
+import io.jsonwebtoken.Claims;
 import jakarta.annotation.PostConstruct;
 import jakarta.servlet.ServletContext;
 import org.apache.poi.xwpf.usermodel.XWPFDocument;
@@ -67,6 +69,15 @@ import com.tencentcloudapi.common.exception.TencentCloudSDKException;
 @SuppressWarnings({"rawtypes", "unchecked"})
 public class TestController {
 
+    @Autowired
+    private JwtUtil jwtUtil;
+
+    @GetMapping("/testExtractToken")
+    public Claims extractToken(String token) {
+        Claims claims = jwtUtil.extractAllClaims(token);
+        return claims;
+    }
+
 
     @Value("${tencent.facefusion.secret-id}")
     private String SECRET_ID;

+ 20 - 10
src/main/java/com/backendsys/modules/material/service/impl/MaterialServiceImpl.java

@@ -11,6 +11,8 @@ import com.backendsys.modules.material.entity.Material;
 import com.backendsys.modules.material.entity.MaterialCategory;
 import com.backendsys.modules.material.entity.MaterialTag;
 import com.backendsys.modules.material.service.MaterialService;
+import com.backendsys.modules.system.dao.SysUserRolePermissionRelationDao;
+import com.backendsys.modules.system.dao.SysUserRoleRelationDao;
 import com.backendsys.modules.system.entity.SysUserRole;
 import com.backendsys.modules.system.service.SysUserRoleService;
 import com.backendsys.modules.upload.service.SysFileService;
@@ -25,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -48,6 +51,10 @@ public class MaterialServiceImpl implements MaterialService {
     private SysFileService sysFileService;
     @Autowired
     private SysUserRoleService sysUserRoleService;
+    @Autowired
+    private SysUserRoleRelationDao sysUserRoleRelationDao;
+    @Autowired
+    private SysUserRolePermissionRelationDao sysUserRolePermissionRelationDao;
 
     private List<MaterialTag> getMaterialTagByIds(String tag_ids) {
         if (StrUtil.isEmpty(tag_ids)) return null;
@@ -100,17 +107,20 @@ public class MaterialServiceImpl implements MaterialService {
         List<MaterialTag> materialTagList = getMaterialTagByIds(detail.getTag_ids());
         detail.setTag_list(materialTagList);
 
-        // [DB] 查询当前用户角色,如果是素材游客,则不显示图片
-        List<SysUserRole> role_list = sysUserRoleService.selectUserRoleByUserId(SecurityUtil.getUserId());
-        AtomicReference<Boolean> hasPermission = new AtomicReference<>(false);
-        role_list.stream().forEach(role -> {
-            if ("MATERIAL_USER".equals(role.getRole_sign()) || "MATERIAL_ADMIN".equals(role.getRole_sign())) {
-                hasPermission.set(true);
-            }
-        });
+        // 权限控制:
+
+        // [DB] 获得当前用户的角色关系(集合)
+        List<Long> userRoleIds = sysUserRoleRelationDao.selectUserRoleIds(SecurityUtil.getUserId());
 
-        // 如果当前用户没有权限,则不显示图片
-        if (!hasPermission.get()) {
+        // - ('20.1.5', '20.1', '下载素材', null)
+        List<String> rolePermissionIds = new ArrayList<>();
+        if (userRoleIds.size() > 0) {
+            // [DB] 获得当前用户角色的权限 (集合)
+            rolePermissionIds = sysUserRolePermissionRelationDao.selectUserRolePermissionIdsByRoleIds(userRoleIds);
+            rolePermissionIds = rolePermissionIds.stream().distinct().collect(Collectors.toList());
+        }
+        // 判断是否具备权限
+        if (!rolePermissionIds.contains("20.1.5")) {
             detail.setFile_url("Unauthorized");
             detail.setPan_baidu_url("Unauthorized");
         }

+ 46 - 15
src/main/java/com/backendsys/modules/material/service/impl/MaterialUserServiceImpl.java

@@ -3,14 +3,20 @@ package com.backendsys.modules.material.service.impl;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
 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.CaptchaUtil;
+import com.backendsys.modules.common.config.security.utils.JwtUtil;
 import com.backendsys.modules.common.config.security.utils.LockStatusUtil;
 import com.backendsys.modules.common.config.security.utils.SecurityUtil;
 import com.backendsys.modules.material.entity.MaterialAudit;
 import com.backendsys.modules.material.entity.MaterialUser;
 import com.backendsys.modules.material.service.MaterialUserService;
+import com.backendsys.modules.sse.entity.SseResponse;
+import com.backendsys.modules.sse.entity.SseResponseEnum;
+import com.backendsys.modules.sse.utils.SseUtil;
 import com.backendsys.modules.system.dao.SysUserDao;
 import com.backendsys.modules.system.dao.SysUserInfoDao;
 import com.backendsys.modules.system.dao.SysUserRoleDao;
@@ -20,6 +26,7 @@ import com.backendsys.modules.system.service.SysAuthService;
 import com.backendsys.modules.system.service.SysCommonService;
 import com.backendsys.modules.system.service.SysUserIntegralService;
 import com.backendsys.modules.system.service.SysUserService;
+import com.backendsys.modules.system.utils.UserUtil;
 import com.backendsys.utils.response.PageEntity;
 import com.backendsys.utils.response.PageInfoResult;
 import com.backendsys.utils.v2.PageUtils;
@@ -40,6 +47,11 @@ import java.util.Map;
 @Service
 public class MaterialUserServiceImpl implements MaterialUserService {
 
+    @Autowired
+    private UserUtil userUtil;
+    @Autowired
+    private SseUtil sseUtil;
+
     @Value("${spring.application.name}")
     private String APPLICATION_NAME;
     @Value("${tencent.sms.debug}")
@@ -108,11 +120,11 @@ public class MaterialUserServiceImpl implements MaterialUserService {
     public Map<String, Object> auditMaterialUser(MaterialAudit materialAudit) {
 
         // 判断是否为素材用户 / 用户是否存在
-        LambdaQueryWrapper<SysUserInfo> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(SysUserInfo::getUser_id, materialAudit.getUser_id());
-        wrapper.eq(SysUserInfo::getInvite_code, "Material");
-        SysUserInfo user_info_detail = sysUserInfoDao.selectOne(wrapper);
-        if (user_info_detail == null) throw new CustException("用户不存在");
+        SysUserInfo entity = new SysUserInfo();
+        entity.setUser_id(materialAudit.getUser_id());
+        entity.setInvite_code("Material");
+        SysUserInfo userInfo = sysUserService.selectUserInfo(entity);
+        if (userInfo == null) throw new CustException("用户不存在");
 
         // 判断用户是否待审核状态 (-1审核拒绝, 1待审核, 2审核通过)
         if (materialAudit.getUser_id() == SecurityUtil.getUserId()) throw new CustException("不能审核自己");
@@ -123,15 +135,19 @@ public class MaterialUserServiceImpl implements MaterialUserService {
         if (!role_ids.contains(materialAudit.getRole_id())) throw new CustException("必须指定素材用户角色");
 
         // [DB] 更新用户信息-审核状态/用户状态
-        SysUserInfo entity = new SysUserInfo();
-        entity.setAudit_status(materialAudit.getAudit_status());
-        entity.setStatus(materialAudit.getStatus());
-        sysUserInfoDao.update(entity, wrapper);
+        LambdaQueryWrapper<SysUserInfo> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SysUserInfo::getUser_id, materialAudit.getUser_id());
+        wrapper.eq(SysUserInfo::getInvite_code, "Material");
+        //
+        userInfo.setAudit_status(materialAudit.getAudit_status());
+        userInfo.setAudit_note("素材管理审核通过");
+        userInfo.setStatus(materialAudit.getStatus());
+        sysUserInfoDao.update(userInfo, wrapper);
 
-        // 如果是禁用状态,则清除该用户的登录信息
-        if (materialAudit.getStatus() == -1) {
-            sysUserService.kickUser(materialAudit.getUser_id());
-        }
+//        // 如果是禁用状态,则清除该用户的登录信息
+//        if (materialAudit.getStatus() == -1) {
+//            sysUserService.kickUser(materialAudit.getUser_id());
+//        }
 
         // [DB] 更新用户与角色关系 (先删,后增)
         LambdaQueryWrapper<SysUserRoleRelation> wrapperRoleRelation = new LambdaQueryWrapper<>();
@@ -139,6 +155,21 @@ public class MaterialUserServiceImpl implements MaterialUserService {
         sysUserRoleRelationDao.delete(wrapperRoleRelation);
         sysUserRoleRelationDao.insertBatch(materialAudit.getUser_id(), Arrays.asList(materialAudit.getRole_id()));
 
+
+        // [2025-08-18] 需求:后台加白后,前台踢掉用户,强制让该用户重新登录;
+        // https://www.tapd.cn/tapd_fe/61244365/story/detail/1161244365001000497
+        sysUserService.kickUser(materialAudit.getUser_id());
+
+//        // 重置的过期时间直接给7天
+//        Long tokenDurationMilliseconds = userUtil.getTokenDuration(true);
+//        Integer tokenDurationHours = Convert.toInt(tokenDurationMilliseconds / 3600000L);
+//        // 实时更新缓存: 用户信息
+//        SysUserInfo userInfoLasest = sysUserService.selectUserInfo(entity);
+//        // 赋加缓存时间 { token_expiration }
+//        SysUserInfo userInfoLasestCatch = userUtil.syncUpdateUserCatch(userInfoLasest, tokenDurationHours, true);
+//        // 发送SSE消息到前端
+//        sseUtil.send(userInfoLasestCatch.getUser_id(), new SseResponse(SseResponseEnum.SYSTEM_USER_UPDATE, userInfoLasestCatch).toJsonStr());
+
         return Map.of("user_id", materialAudit.getUser_id());
     }
 
@@ -187,7 +218,7 @@ public class MaterialUserServiceImpl implements MaterialUserService {
         SysUser sysUserDetail = sysUserDao.selectOne(queryWrapper);
         if (sysUserDetail != null) {
             // [已注册] 返回登录信息 (并且7天免登录)
-            SysUserInfo sysUserInfo = sysAuthService.loginSuccess(sysUserDetail.getId(), 1);
+            SysUserInfo sysUserInfo = sysAuthService.loginSuccess(sysUserDetail.getId(), true);
             Map<String, Object> response = BeanUtil.beanToMap(sysUserInfo);
             response.put("is_register", false);
             return response;
@@ -221,7 +252,7 @@ public class MaterialUserServiceImpl implements MaterialUserService {
             sysUserIntegralService.init(registerEntity.getId());
 
             // [DB] 查询用户信息
-            SysUserInfo sysUserInfo = sysAuthService.loginSuccess(registerEntity.getId(), 1);
+            SysUserInfo sysUserInfo = sysAuthService.loginSuccess(registerEntity.getId(), true);
             Map<String, Object> response = BeanUtil.beanToMap(sysUserInfo);
             response.put("is_register", true);
             return response;

+ 2 - 0
src/main/java/com/backendsys/modules/sse/entity/SseResponseEnum.java

@@ -2,6 +2,8 @@ package com.backendsys.modules.sse.entity;
 
 public enum SseResponseEnum {
 
+    SYSTEM_USER_UPDATE("system_user_update", "更新用户信息"),
+
     CONNECT("connect", "建立连接"),
     DISCONNECT("disconnect", "断开连接"),
     LOGOUT("logout", "退出登录"),

+ 1 - 1
src/main/java/com/backendsys/modules/system/entity/SysAuth.java

@@ -21,5 +21,5 @@ public class SysAuth {
     // @NotEmpty(message="验证码不能为空", groups = { Login.class, Register.class })
     private String captcha;
 
-    private Integer is_remember;
+    private Boolean is_remember;
 }

+ 1 - 1
src/main/java/com/backendsys/modules/system/entity/SysAuthPhone.java

@@ -29,5 +29,5 @@ public class SysAuthPhone {
     @Max(value = 999999, message = "验证码长度是 6 位字符", groups = { Register.class })
     private Integer phone_valid_code;
 
-    private Integer is_remember;
+    private Boolean is_remember;
 }

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

@@ -24,5 +24,5 @@ public interface SysAuthService {
     void loginFail(String errMsg, String username, Boolean isIntercept);
     void cleanLoginRequired(String key);
     // [方法] 登录成功
-    SysUserInfo loginSuccess(Long user_id, Integer is_remember);
+    SysUserInfo loginSuccess(Long user_id, Boolean is_remember);
 }

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

@@ -14,7 +14,7 @@ public interface SysUserService extends IService<SysUser> {
     PageEntity selectUserOnlineList(SysUserDTO sysUserDTO);
 
     // 获取系统用户详情
-    SysUserInfo selectUserInfo(Long user_id);
+    SysUserInfo selectUserInfo(SysUserInfo sysUserInfo);
     // 获取系统用户详情(简约)
     SysUserInfoSimple selectUserInfoSimple(Long user_id);
 

+ 35 - 25
src/main/java/com/backendsys/modules/system/service/impl/SysAuthServiceImpl.java

@@ -19,6 +19,7 @@ import com.backendsys.modules.system.service.SysAuthService;
 import com.backendsys.modules.system.service.SysCommonService;
 import com.backendsys.modules.system.service.SysUserIntegralService;
 import com.backendsys.modules.system.service.SysUserService;
+import com.backendsys.modules.system.utils.UserUtil;
 import com.backendsys.utils.response.ResultEnum;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.google.code.kaptcha.Producer;
@@ -47,6 +48,8 @@ public class SysAuthServiceImpl implements SysAuthService {
     @Autowired
     private Environment env;
     @Autowired
+    private UserUtil userUtil;
+    @Autowired
     private JwtUtil jwtUtil;
     @Autowired
     private RedisUtil redisUtil;
@@ -149,10 +152,12 @@ public class SysAuthServiceImpl implements SysAuthService {
     }
 
     // [方法] 登录成功
-    public SysUserInfo loginSuccess(Long user_id, Integer is_remember) {
+    public SysUserInfo loginSuccess(Long user_id, Boolean is_remember) {
 
         // [查询] 登录的用户信息
-        SysUserInfo sysUserInfo = sysUserService.selectUserInfo(user_id);
+        SysUserInfo entity = new SysUserInfo();
+        entity.setUser_id(user_id);
+        SysUserInfo sysUserInfo = sysUserService.selectUserInfo(entity);
 
         // 删除图形验证码缓存
         redisUtil.delete(httpRequestUtil.getKaptchaKey());
@@ -181,31 +186,36 @@ public class SysAuthServiceImpl implements SysAuthService {
         sysUserInfo.setLast_login_time(LocalDateTime.now(ZoneOffset.UTC));
         sysUserInfoDao.updateById(sysUserInfo);
 
-        // [系统配置] 系统用户默认登录过期时间(小时)
-        Integer SYSTEM_USER_LOGIN_DURATION_DEFAULT = Convert.toInt(sysCommonService.getCommonByTag("SYSTEM_USER_LOGIN_DURATION_DEFAULT"));
-        // 将小时转换为毫秒
-        Long DEFAULT_MILLISECONDS = SYSTEM_USER_LOGIN_DURATION_DEFAULT * DateUnit.HOUR.getMillis();
-        // 7天 (转毫秒)
-        Long SEVEN_DAY_MILLISECONDS = 7L * 24 * 60 * 60 * 1000;
-
-        Long token_duration_milliseconds = (is_remember != null && is_remember.equals(1)) ? SEVEN_DAY_MILLISECONDS : DEFAULT_MILLISECONDS;
-        Integer token_duration_hours = Convert.toInt(token_duration_milliseconds / 3600000L);
-
-        Date token_expiration = new Date((new Date()).getTime() + token_duration_milliseconds);
+//        // [系统配置] 系统用户默认登录过期时间(小时)
+//        Integer SYSTEM_USER_LOGIN_DURATION_DEFAULT = Convert.toInt(sysCommonService.getCommonByTag("SYSTEM_USER_LOGIN_DURATION_DEFAULT"));
+//        // 将小时转换为毫秒
+//        Long DEFAULT_MILLISECONDS = SYSTEM_USER_LOGIN_DURATION_DEFAULT * DateUnit.HOUR.getMillis();
+//        // 7天 (转毫秒)
+//        Long SEVEN_DAY_MILLISECONDS = 7L * 24 * 60 * 60 * 1000;
+//        // 是否钩选 "7天免登录",否则按系统配置-默认过期时间
+//        Long token_duration_milliseconds = (is_remember != null && is_remember.equals(1)) ? SEVEN_DAY_MILLISECONDS : DEFAULT_MILLISECONDS;
+//        Integer tokenDurationHours = Convert.toInt(token_duration_milliseconds / 3600000L);
+
+        Long tokenDurationMilliseconds = userUtil.getTokenDuration(is_remember);
+        Integer tokenDurationHours = Convert.toInt(tokenDurationMilliseconds / 3600000L);
+        Date token_expiration = new Date((new Date()).getTime() + tokenDurationMilliseconds);
         sysUserInfo.setToken_expiration(DateUtil.format(token_expiration, "yyyy-MM-dd HH:mm:ss"));
 
-        // 生成 Token
-        SecurityUserInfo securityUserInfo = JSONUtil.toBean(JSONUtil.parseObj(sysUserInfo), SecurityUserInfo.class);
-        String token = jwtUtil.createSystemJwtToken(securityUserInfo);
-        String token_redis_key = REDIS_LOGIN_TOKEN_PREFIX + uuid;
-        sysUserInfo.setToken(token);
-
-        // 生成 PerMissionIds
-        List<String> permission_ids_list = sysUserInfo.getPermission_ids();
-
-        // [Redis] 将 Token 与 Permission 存入缓存
-        TokenCatch tokenCatch = new TokenCatch(token, permission_ids_list);
-        redisUtil.setCacheObject(token_redis_key, JSONUtil.toJsonStr(tokenCatch), token_duration_hours, TimeUnit.HOURS);
+        // 实时更新缓存: 用户信息
+        sysUserInfo = userUtil.syncUpdateUserCatch(sysUserInfo, tokenDurationHours, is_remember);
+
+        //// 生成 Token
+        //SecurityUserInfo securityUserInfo = JSONUtil.toBean(JSONUtil.parseObj(sysUserInfo), SecurityUserInfo.class);
+        //String token = jwtUtil.createSystemJwtToken(securityUserInfo);
+        //sysUserInfo.setToken(token);
+        //
+        //// 生成 PerMissionIds
+        //List<String> permission_ids_list = sysUserInfo.getPermission_ids();
+        //
+        //// [Redis] 将 Token 与 Permission 存入缓存
+        //String token_redis_key = REDIS_LOGIN_TOKEN_PREFIX + uuid;
+        //TokenCatch tokenCatch = new TokenCatch(token, permission_ids_list);
+        //redisUtil.setCacheObject(token_redis_key, JSONUtil.toJsonStr(tokenCatch), token_duration_hours, TimeUnit.HOURS);
 
         return sysUserInfo;
     }

+ 30 - 10
src/main/java/com/backendsys/modules/system/service/impl/SysUserServiceImpl.java

@@ -1,6 +1,7 @@
 package com.backendsys.modules.system.service.impl;
 
 import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
 import com.backendsys.exception.CustException;
 import com.backendsys.modules.common.config.redis.utils.RedisUtil;
 import com.backendsys.modules.common.config.security.utils.SecurityUtil;
@@ -100,14 +101,23 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> impleme
      * 获取系统用户详情
      */
     @Override
-    public SysUserInfo selectUserInfo(Long user_id) {
+    public SysUserInfo selectUserInfo(SysUserInfo entity) {
+
+        Long user_id = entity.getUser_id();
 
         // 获得 用户账号信息
         SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", user_id));
         if (sysUser == null) throw new CustException("用户不存在");
 
         // 获得 用户基本信息
-        SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
+        LambdaQueryWrapper<SysUserInfo> wrapperUserInfo = new LambdaQueryWrapper<>();
+        // 条件:用户ID (必选)
+        wrapperUserInfo.eq(SysUserInfo::getUser_id, user_id);
+        // 条件:邀请码
+        if (StrUtil.isNotEmpty(entity.getInvite_code())) {
+            wrapperUserInfo.eq(SysUserInfo::getInvite_code, entity.getInvite_code());
+        }
+        SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(wrapperUserInfo);
         if (sysUserInfo == null) throw new CustException("用户不存在");
 
         // 用户账号信息 赋值到 用户基本信息
@@ -464,15 +474,25 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> impleme
             SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(queryWrapper);
 
             if (sysUserInfo != null) {
-                // 删除旧的登录缓存
-                tokenUtil.deleteRedisLoginToken(sysUserInfo.getLast_login_uuid());
-                // 更新用户信息 (查询最后登录uuid,并清除)
-                Wrapper updateWrapper = new UpdateWrapper<SysUserInfo>().lambda().set(SysUserInfo::getLast_login_uuid, "").eq(SysUserInfo::getUser_id, user_id);
-                sysUserInfoDao.update(null, updateWrapper);
 
-                // [SSE] 发送退出登录的消息
-                String dataStr = (new SseResponse(SseResponseEnum.LOGOUT)).toJsonStr();
-                sseUtil.send(sysUserInfo.getUser_id(), dataStr);
+                // 判断 Token 是否存在
+                String uuid = sysUserInfo.getLast_login_uuid();
+                String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + uuid;
+                System.out.println("tokenRedisKey = " + tokenRedisKey);
+                Object isExist = redisUtil.getCacheObject(tokenRedisKey);
+
+                if (isExist != null) {
+                    // 删除旧的登录缓存
+                    tokenUtil.deleteRedisLoginToken(uuid);
+                    // 更新用户信息 (查询最后登录uuid,并清除)
+                    Wrapper updateWrapper = new UpdateWrapper<SysUserInfo>().lambda().set(SysUserInfo::getLast_login_uuid, "").eq(SysUserInfo::getUser_id, user_id);
+                    sysUserInfoDao.update(null, updateWrapper);
+
+                    // [SSE] 发送退出登录的消息
+                    String dataStr = (new SseResponse(SseResponseEnum.LOGOUT)).toJsonStr();
+                    sseUtil.send(sysUserInfo.getUser_id(), dataStr);
+                }
+
             }
 
             return Map.of("user_id", user_id);

+ 80 - 0
src/main/java/com/backendsys/modules/system/utils/UserUtil.java

@@ -0,0 +1,80 @@
+package com.backendsys.modules.system.utils;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+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.JwtUtil;
+import com.backendsys.modules.system.entity.SysUserInfo;
+import com.backendsys.modules.system.entity.TokenCatch;
+import com.backendsys.modules.system.service.SysCommonService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class UserUtil {
+
+    @Autowired
+    private JwtUtil jwtUtil;
+    @Autowired
+    private RedisUtil redisUtil;
+    
+    @Autowired
+    private SysCommonService sysCommonService;
+
+    @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
+    private String REDIS_LOGIN_TOKEN_PREFIX;
+
+    public static final long SEVEN_DAYS_MILLIS = 7L * 24 * 60 * 60 * 1000;
+
+    /**
+     * 实时更新缓存: 用户信息
+     */
+    public SysUserInfo syncUpdateUserCatch(SysUserInfo userInfo, Integer tokenDurationHours, Boolean isRemember) {
+
+        // -- 重置过期时间 -----------------------------------
+        Integer durationHours = tokenDurationHours != null ? tokenDurationHours : Convert.toInt(SEVEN_DAYS_MILLIS / 3600000L);
+        Long tokenDurationMilliseconds = getTokenDuration(isRemember);
+        Date tokenExpiration = new Date((new Date()).getTime() + tokenDurationMilliseconds);
+        userInfo.setToken_expiration(DateUtil.format(tokenExpiration, "yyyy-MM-dd HH:mm:ss"));
+
+        // 生成 Token
+        String lastLoginUuid = userInfo.getLast_login_uuid();
+        SecurityUserInfo securityUserInfo = JSONUtil.toBean(JSONUtil.parseObj(userInfo), SecurityUserInfo.class);
+
+        String token = jwtUtil.createSystemJwtToken(securityUserInfo);
+        userInfo.setToken(token);
+
+        // [Redis] 将 Token 与 Permission 存入缓存
+        String tokenRedisKey = REDIS_LOGIN_TOKEN_PREFIX + lastLoginUuid;
+        TokenCatch tokenCatch = new TokenCatch(token, userInfo.getPermission_ids());
+        redisUtil.setCacheObject(tokenRedisKey, JSONUtil.toJsonStr(tokenCatch), durationHours, TimeUnit.HOURS);
+
+        System.out.println("syncUpdateUserCatch = " + userInfo);
+
+        return userInfo;
+    }
+
+
+    /**
+     * 获得登录过期时间 (毫秒)
+     */
+    public Long getTokenDuration(Boolean isRemember) {
+        System.out.println("isRemember = " + isRemember);
+        // [系统配置] 系统用户默认登录过期时间(小时)
+        Integer SYSTEM_USER_LOGIN_DURATION_DEFAULT = Convert.toInt(sysCommonService.getCommonByTag("SYSTEM_USER_LOGIN_DURATION_DEFAULT"));
+        // 将小时转换为毫秒
+        Long DEFAULT_MILLISECONDS = SYSTEM_USER_LOGIN_DURATION_DEFAULT * DateUnit.HOUR.getMillis();
+        // 是否钩选 "7天免登录",否则按系统配置-默认过期时间
+        Long tokenDurationMilliseconds = isRemember ? SEVEN_DAYS_MILLIS : DEFAULT_MILLISECONDS;
+        return tokenDurationMilliseconds;
+    }
+}

+ 3 - 1
src/main/java/com/backendsys/service/Ai/Aiivh/AiivhQuotaServiceImpl.java

@@ -270,7 +270,9 @@ public class AiivhQuotaServiceImpl implements AiivhQuotaService{
 //            Map<String, Object> userInfo = sysUserService.queryUserById(user_id);
 //            Float origin_point_balance = (Float) userInfo.get("point_balance");
 
-            SysUserInfo userInfo = sysUserService.selectUserInfo(user_id);
+            SysUserInfo entity = new SysUserInfo();
+            entity.setUser_id(user_id);
+            SysUserInfo userInfo = sysUserService.selectUserInfo(entity);
             Float origin_point_balance = Convert.toFloat(userInfo.getPoint_balance());
 
             Float new_point_balance = origin_point_balance - aiivhQuotaOrderDTO.getTotal_point();