Procházet zdrojové kódy

add 新增 通用翻译注解及实现(部门名、字典、oss、用户名)

疯狂的狮子li před 2 roky
rodič
revize
bc06550918
18 změnil soubory, kde provedl 480 přidání a 8 odebrání
  1. 39 0
      ruoyi-common/src/main/java/com/ruoyi/common/annotation/Translation.java
  2. 21 0
      ruoyi-common/src/main/java/com/ruoyi/common/annotation/TranslationType.java
  3. 10 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java
  4. 30 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/TransConstant.java
  5. 18 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/service/DeptService.java
  6. 18 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/service/OssService.java
  7. 18 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/service/UserService.java
  8. 17 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/TranslationInterface.java
  9. 29 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationBeanSerializerModifier.java
  10. 65 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationHandler.java
  11. 25 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DeptNameTranslationImpl.java
  12. 29 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DictTypeTranslationImpl.java
  13. 25 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/OssUrlTranslationImpl.java
  14. 28 0
      ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/UserNameTranslationImpl.java
  15. 50 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/TranslationConfig.java
  16. 31 2
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
  17. 15 5
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
  18. 12 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

+ 39 - 0
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Translation.java

@@ -0,0 +1,39 @@
+package com.ruoyi.common.annotation;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.translation.handler.TranslationHandler;
+
+import java.lang.annotation.*;
+
+/**
+ * 通用翻译注解
+ *
+ * @author Lion Li
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+@Documented
+@JacksonAnnotationsInside
+@JsonSerialize(using = TranslationHandler.class)
+public @interface Translation {
+
+    /**
+     * 类型 (需与实现类上的 {@link com.ruoyi.common.annotation.TranslationType} 注解type对应)
+     * <p>
+     * 默认取当前字段的值 如果设置了 @{@link Translation#mapper()} 则取映射字段的值
+     */
+    String type();
+
+    /**
+     * 映射字段 (如果不为空则取此字段的值)
+     */
+    String mapper() default "";
+
+    /**
+     * 其他条件 例如: 字典type(sys_user_sex)
+     */
+    String other() default "";
+
+}

+ 21 - 0
ruoyi-common/src/main/java/com/ruoyi/common/annotation/TranslationType.java

@@ -0,0 +1,21 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 翻译类型注解 (标注到{@link com.ruoyi.common.translation.TranslationInterface} 的实现类)
+ *
+ * @author Lion Li
+ */
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Documented
+public @interface TranslationType {
+
+    /**
+     * 类型
+     */
+    String type();
+
+}

+ 10 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java

@@ -31,6 +31,16 @@ public interface CacheNames {
     String SYS_DICT = "sys_dict";
 
     /**
+     * 用户账户
+     */
+    String SYS_USER_NAME = "sys_user_name#30d";
+
+    /**
+     * 部门
+     */
+    String SYS_DEPT = "sys_dept#30d";
+
+    /**
      * OSS内容
      */
     String SYS_OSS = "sys_oss#30d";

+ 30 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/TransConstant.java

@@ -0,0 +1,30 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 翻译常量
+ *
+ * @author Lion Li
+ */
+public interface TransConstant {
+
+    /**
+     * 用户id转账号
+     */
+    String USER_ID_TO_NAME = "user_id_to_name";
+
+    /**
+     * 部门id转名称
+     */
+    String DEPT_ID_TO_NAME = "dept_id_to_name";
+
+    /**
+     * 字典type转label
+     */
+    String DICT_TYPE_TO_LABEL = "dict_type_to_label";
+
+    /**
+     * ossId转url
+     */
+    String OSS_ID_TO_URL = "oss_id_to_url";
+
+}

+ 18 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/service/DeptService.java

@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.service;
+
+/**
+ * 通用 部门服务
+ *
+ * @author Lion Li
+ */
+public interface DeptService {
+
+    /**
+     * 通过部门ID查询部门名称
+     *
+     * @param deptIds 部门ID串逗号分隔
+     * @return 部门名称串逗号分隔
+     */
+    String selectDeptNameByIds(String deptIds);
+
+}

+ 18 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/service/OssService.java

@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.service;
+
+/**
+ * 通用 OSS服务
+ *
+ * @author Lion Li
+ */
+public interface OssService {
+
+    /**
+     * 通过ossId查询对应的url
+     *
+     * @param ossIds ossId串逗号分隔
+     * @return url串逗号分隔
+     */
+    String selectUrlByIds(String ossIds);
+
+}

+ 18 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/service/UserService.java

@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.service;
+
+/**
+ * 通用 用户服务
+ *
+ * @author Lion Li
+ */
+public interface UserService {
+
+    /**
+     * 通过用户ID查询用户账户
+     *
+     * @param userId 用户ID
+     * @return 用户账户
+     */
+    String selectUserNameById(Long userId);
+
+}

+ 17 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/TranslationInterface.java

@@ -0,0 +1,17 @@
+package com.ruoyi.common.translation;
+
+/**
+ * 翻译接口 (实现类需标注 {@link com.ruoyi.common.annotation.TranslationType} 注解标明翻译类型)
+ *
+ * @author Lion Li
+ */
+public interface TranslationInterface {
+
+    /**
+     * 翻译
+     *
+     * @param key 需要被翻译的键(不为空)
+     * @return 返回键对应的值
+     */
+    String translation(Object key, String other);
+}

+ 29 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationBeanSerializerModifier.java

@@ -0,0 +1,29 @@
+package com.ruoyi.common.translation.handler;
+
+import com.fasterxml.jackson.databind.BeanDescription;
+import com.fasterxml.jackson.databind.SerializationConfig;
+import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
+import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
+
+import java.util.List;
+
+/**
+ * Bean 序列化修改器 解决 Null 被单独处理问题
+ *
+ * @author Lion Li
+ */
+public class TranslationBeanSerializerModifier extends BeanSerializerModifier {
+
+    @Override
+    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
+                                                     List<BeanPropertyWriter> beanProperties) {
+        for (BeanPropertyWriter writer : beanProperties) {
+            // 如果序列化器为 TranslationHandler 的话 将 Null 值也交给他处理
+            if (writer.getSerializer() instanceof TranslationHandler) {
+                writer.assignNullSerializer(writer.getSerializer());
+            }
+        }
+        return beanProperties;
+    }
+
+}

+ 65 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/handler/TranslationHandler.java

@@ -0,0 +1,65 @@
+package com.ruoyi.common.translation.handler;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.ruoyi.common.annotation.Translation;
+import com.ruoyi.common.translation.TranslationInterface;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 翻译处理器
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class TranslationHandler extends JsonSerializer<Object> implements ContextualSerializer {
+
+    /**
+     * 全局翻译实现类映射器
+     */
+    public static final Map<String, TranslationInterface> TRANSLATION_MAPPER = new ConcurrentHashMap<>();
+
+    private Translation translation;
+
+    @Override
+    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+        TranslationInterface trans = TRANSLATION_MAPPER.get(translation.type());
+        if (ObjectUtil.isNotNull(trans)) {
+            // 如果映射字段不为空 则取映射字段的值
+            if (StringUtils.isNotBlank(translation.mapper())) {
+                value = ReflectUtils.invokeGetter(gen.getCurrentValue(), translation.mapper());
+            }
+            // 如果为 null 直接写出
+            if (ObjectUtil.isNull(value)) {
+                gen.writeNull();
+                return;
+            }
+            String result = trans.translation(value, translation.other());
+            gen.writeString(result);
+        } else {
+            gen.writeObject(value);
+        }
+    }
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
+        Translation translation = property.getAnnotation(Translation.class);
+        if (Objects.nonNull(translation)) {
+            this.translation = translation;
+            return this;
+        }
+        return prov.findValueSerializer(property.getType(), property);
+    }
+}

+ 25 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DeptNameTranslationImpl.java

@@ -0,0 +1,25 @@
+package com.ruoyi.common.translation.impl;
+
+import com.ruoyi.common.annotation.TranslationType;
+import com.ruoyi.common.constant.TransConstant;
+import com.ruoyi.common.core.service.DeptService;
+import com.ruoyi.common.translation.TranslationInterface;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+
+/**
+ * 部门翻译实现
+ *
+ * @author Lion Li
+ */
+@Component
+@AllArgsConstructor
+@TranslationType(type = TransConstant.DEPT_ID_TO_NAME)
+public class DeptNameTranslationImpl implements TranslationInterface {
+
+    private final DeptService deptService;
+
+    public String translation(Object key, String other) {
+        return deptService.selectDeptNameByIds(key.toString());
+    }
+}

+ 29 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/DictTypeTranslationImpl.java

@@ -0,0 +1,29 @@
+package com.ruoyi.common.translation.impl;
+
+import com.ruoyi.common.annotation.TranslationType;
+import com.ruoyi.common.constant.TransConstant;
+import com.ruoyi.common.core.service.DictService;
+import com.ruoyi.common.translation.TranslationInterface;
+import com.ruoyi.common.utils.StringUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+
+/**
+ * 字典翻译实现
+ *
+ * @author Lion Li
+ */
+@Component
+@AllArgsConstructor
+@TranslationType(type = TransConstant.DICT_TYPE_TO_LABEL)
+public class DictTypeTranslationImpl implements TranslationInterface {
+
+    private final DictService dictService;
+
+    public String translation(Object key, String other) {
+        if (key instanceof String && StringUtils.isNotBlank(other)) {
+            return dictService.getDictLabel(other, key.toString());
+        }
+        return null;
+    }
+}

+ 25 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/OssUrlTranslationImpl.java

@@ -0,0 +1,25 @@
+package com.ruoyi.common.translation.impl;
+
+import com.ruoyi.common.annotation.TranslationType;
+import com.ruoyi.common.constant.TransConstant;
+import com.ruoyi.common.core.service.OssService;
+import com.ruoyi.common.translation.TranslationInterface;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+
+/**
+ * OSS翻译实现
+ *
+ * @author Lion Li
+ */
+@Component
+@AllArgsConstructor
+@TranslationType(type = TransConstant.OSS_ID_TO_URL)
+public class OssUrlTranslationImpl implements TranslationInterface {
+
+    private final OssService ossService;
+
+    public String translation(Object key, String other) {
+        return ossService.selectUrlByIds(key.toString());
+    }
+}

+ 28 - 0
ruoyi-common/src/main/java/com/ruoyi/common/translation/impl/UserNameTranslationImpl.java

@@ -0,0 +1,28 @@
+package com.ruoyi.common.translation.impl;
+
+import com.ruoyi.common.annotation.TranslationType;
+import com.ruoyi.common.constant.TransConstant;
+import com.ruoyi.common.core.service.UserService;
+import com.ruoyi.common.translation.TranslationInterface;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+
+/**
+ * 用户名翻译实现
+ *
+ * @author Lion Li
+ */
+@Component
+@AllArgsConstructor
+@TranslationType(type = TransConstant.USER_ID_TO_NAME)
+public class UserNameTranslationImpl implements TranslationInterface {
+
+    private final UserService userService;
+
+    public String translation(Object key, String other) {
+        if (key instanceof Long) {
+            return userService.selectUserNameById((Long) key);
+        }
+        return null;
+    }
+}

+ 50 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/TranslationConfig.java

@@ -0,0 +1,50 @@
+package com.ruoyi.framework.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.annotation.TranslationType;
+import com.ruoyi.common.translation.TranslationInterface;
+import com.ruoyi.common.translation.handler.TranslationBeanSerializerModifier;
+import com.ruoyi.common.translation.handler.TranslationHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 翻译模块配置类
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@Configuration
+public class TranslationConfig {
+
+    @Autowired
+    private List<TranslationInterface> list;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @PostConstruct
+    public void init() {
+        Map<String, TranslationInterface> map = new HashMap<>(list.size());
+        for (TranslationInterface trans : list) {
+            if (trans.getClass().isAnnotationPresent(TranslationType.class)) {
+                TranslationType annotation = trans.getClass().getAnnotation(TranslationType.class);
+                map.put(annotation.type(), trans);
+            } else {
+                log.warn(trans.getClass().getName() + " 翻译实现类未标注 TranslationType 注解!");
+            }
+        }
+        TranslationHandler.TRANSLATION_MAPPER.putAll(map);
+        // 设置 Bean 序列化修改器
+        objectMapper.setSerializerFactory(
+            objectMapper.getSerializerFactory()
+                .withSerializerModifier(new TranslationBeanSerializerModifier()));
+    }
+
+}

+ 31 - 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java

@@ -6,25 +6,32 @@ import cn.hutool.core.lang.tree.Tree;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.ruoyi.common.constant.CacheNames;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.service.DeptService;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.helper.DataBaseHelper;
 import com.ruoyi.common.helper.LoginHelper;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.TreeBuildUtils;
+import com.ruoyi.common.utils.redis.CacheUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.system.mapper.SysDeptMapper;
 import com.ruoyi.system.mapper.SysRoleMapper;
 import com.ruoyi.system.mapper.SysUserMapper;
 import com.ruoyi.system.service.ISysDeptService;
 import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 部门管理 服务实现
@@ -33,7 +40,7 @@ import java.util.List;
  */
 @RequiredArgsConstructor
 @Service
-public class SysDeptServiceImpl implements ISysDeptService {
+public class SysDeptServiceImpl implements ISysDeptService, DeptService {
 
     private final SysDeptMapper baseMapper;
     private final SysRoleMapper roleMapper;
@@ -106,6 +113,7 @@ public class SysDeptServiceImpl implements ISysDeptService {
      * @param deptId 部门ID
      * @return 部门信息
      */
+    @Cacheable(cacheNames = CacheNames.SYS_DEPT, key = "#deptId")
     @Override
     public SysDept selectDeptById(Long deptId) {
         SysDept dept = baseMapper.selectById(deptId);
@@ -116,6 +124,24 @@ public class SysDeptServiceImpl implements ISysDeptService {
     }
 
     /**
+     * 通过部门ID查询部门名称
+     *
+     * @param deptIds 部门ID串逗号分隔
+     * @return 部门名称串逗号分隔
+     */
+    @Override
+    public String selectDeptNameByIds(String deptIds) {
+        List<String> list = new ArrayList<>();
+        for (Long id : Arrays.stream(deptIds.split(",")).map(Long::parseLong).collect(Collectors.toList())) {
+            SysDept dept = SpringUtils.getAopProxy(this).selectDeptById(id);
+            if (ObjectUtil.isNotNull(dept)) {
+                list.add(dept.getDeptName());
+            }
+        }
+        return String.join(",", list);
+    }
+
+    /**
      * 根据ID查询所有子部门数(正常状态)
      *
      * @param deptId 部门ID
@@ -260,7 +286,9 @@ public class SysDeptServiceImpl implements ISysDeptService {
             list.add(dept);
         }
         if (CollUtil.isNotEmpty(list)) {
-            baseMapper.updateBatchById(list);
+            if (baseMapper.updateBatchById(list)) {
+                list.forEach(dept -> CacheUtils.evict(CacheNames.SYS_DEPT, dept.getDeptId()));
+            }
         }
     }
 
@@ -270,6 +298,7 @@ public class SysDeptServiceImpl implements ISysDeptService {
      * @param deptId 部门ID
      * @return 结果
      */
+    @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#deptId")
     @Override
     public int deleteDeptById(Long deptId) {
         return baseMapper.deleteById(deptId);

+ 15 - 5
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.constant.CacheNames;
 import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.service.OssService;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.BeanCopyUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -31,10 +32,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -44,7 +42,7 @@ import java.util.stream.Collectors;
  */
 @RequiredArgsConstructor
 @Service
-public class SysOssServiceImpl implements ISysOssService {
+public class SysOssServiceImpl implements ISysOssService, OssService {
 
     private final SysOssMapper baseMapper;
 
@@ -69,6 +67,18 @@ public class SysOssServiceImpl implements ISysOssService {
         return list;
     }
 
+    @Override
+    public String selectUrlByIds(String ossIds) {
+        List<String> list = new ArrayList<>();
+        for (Long id : Arrays.stream(ossIds.split(",")).map(Long::parseLong).collect(Collectors.toList())) {
+            SysOssVo vo = SpringUtils.getAopProxy(this).getById(id);
+            if (ObjectUtil.isNotNull(vo)) {
+                list.add(this.matchingUrl(vo).getUrl());
+            }
+        }
+        return String.join(",", list);
+    }
+
     private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<SysOss> lqw = Wrappers.lambdaQuery();

+ 12 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -9,12 +9,14 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.constant.CacheNames;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.service.UserService;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.helper.DataBaseHelper;
 import com.ruoyi.common.helper.LoginHelper;
@@ -27,6 +29,7 @@ import com.ruoyi.system.mapper.*;
 import com.ruoyi.system.service.ISysUserService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -42,7 +45,7 @@ import java.util.Map;
 @Slf4j
 @RequiredArgsConstructor
 @Service
-public class SysUserServiceImpl implements ISysUserService {
+public class SysUserServiceImpl implements ISysUserService, UserService {
 
     private final SysUserMapper baseMapper;
     private final SysDeptMapper deptMapper;
@@ -480,4 +483,12 @@ public class SysUserServiceImpl implements ISysUserService {
         return baseMapper.deleteBatchIds(ids);
     }
 
+    @Cacheable(cacheNames = CacheNames.SYS_USER_NAME, key = "#userId")
+    @Override
+    public String selectUserNameById(Long userId) {
+        SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+            .select(SysUser::getUserName).eq(SysUser::getUserId, userId));
+        return ObjectUtil.isNull(sysUser) ? null : sysUser.getUserName();
+    }
+
 }