diff --git a/heritage-plugins/heritage-desensitize/pom.xml b/heritage-plugins/heritage-desensitize/pom.xml
new file mode 100644
index 0000000..73bc194
--- /dev/null
+++ b/heritage-plugins/heritage-desensitize/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+ org.leocoder.heritage
+ heritage-plugins
+ ${revision}
+
+
+
+ heritage-desensitize
+ heritage-desensitize
+ 数据脱敏插件
+
+
+
+
+ org.leocoder.heritage
+ heritage-common
+ ${revision}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
\ No newline at end of file
diff --git a/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/anno/CoderDesensitize.java b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/anno/CoderDesensitize.java
new file mode 100755
index 0000000..9393e10
--- /dev/null
+++ b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/anno/CoderDesensitize.java
@@ -0,0 +1,39 @@
+package org.leocoder.heritage.desensitize.anno;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.leocoder.heritage.desensitize.config.DesensitizeJsonSerializer;
+import org.leocoder.heritage.desensitize.enums.DesensitizeRuleEnum;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author Leocoder
+ * @description [CoderDesensitize]
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@JacksonAnnotationsInside
+@JsonSerialize(using = DesensitizeJsonSerializer.class)
+public @interface CoderDesensitize {
+
+ /**
+ * 脱敏数据类型,在MY_RULE的时候,startInclude和endExclude生效
+ */
+ DesensitizeRuleEnum rule() default DesensitizeRuleEnum.CODER_RULE;
+
+ /**
+ * 脱敏开始位置[不包含]
+ */
+ int beginExclude() default 0;
+
+ /**
+ * 脱敏结束位置[包含]
+ */
+ int endInclude() default 0;
+
+
+}
diff --git a/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/anno/EnableCoderDesensitize.java b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/anno/EnableCoderDesensitize.java
new file mode 100755
index 0000000..f60348f
--- /dev/null
+++ b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/anno/EnableCoderDesensitize.java
@@ -0,0 +1,17 @@
+package org.leocoder.heritage.desensitize.anno;
+
+import org.leocoder.heritage.desensitize.config.DesensitizeJsonSerializer;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+// 可用在字段上。
+@Target({ElementType.TYPE})
+// 运行时生效。
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+@Import({ DesensitizeJsonSerializer.class })
+public @interface EnableCoderDesensitize {
+
+}
diff --git a/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/config/DesensitizeJsonSerializer.java b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/config/DesensitizeJsonSerializer.java
new file mode 100755
index 0000000..94bf487
--- /dev/null
+++ b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/config/DesensitizeJsonSerializer.java
@@ -0,0 +1,124 @@
+package org.leocoder.heritage.desensitize.config;
+
+import cn.hutool.core.text.CharSequenceUtil;
+import cn.hutool.core.util.DesensitizedUtil;
+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 lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import org.leocoder.heritage.common.satoken.CoderLoginUtil;
+import org.leocoder.heritage.desensitize.anno.CoderDesensitize;
+import org.leocoder.heritage.desensitize.enums.DesensitizeRuleEnum;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * @author Leocoder
+ * @description [DesensitizeSerialize自定义序列化类]
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+public class DesensitizeJsonSerializer extends JsonSerializer implements ContextualSerializer {
+
+ private DesensitizeRuleEnum ruleEnum;
+
+ private Integer beginExclude;
+
+ private Integer endInclude;
+
+
+ public DesensitizeJsonSerializer(DesensitizeRuleEnum rule, int beginExclude, int endInclude, String[] strings) {
+ }
+
+ @Override
+ public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ // 绑定的需要脱敏的部门ID
+ try {
+ boolean isCoderAdmin = CoderLoginUtil.getIsCoderAdmin();
+ if(isCoderAdmin) {
+ // 无脱敏部门数据,直接写入原始值
+ jsonGenerator.writeString(str);
+ return;
+ }
+ } catch (Exception ignored) {
+
+ }
+ switch (ruleEnum) {
+ // 自定义类型脱敏
+ case CODER_RULE:
+ jsonGenerator.writeString(CharSequenceUtil.hide(str, beginExclude, endInclude));
+ break;
+ // userId脱敏
+ case USER_ID:
+ jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
+ break;
+ // 中文姓名脱敏
+ case CHINESE_NAME:
+ jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));
+ break;
+ // 身份证脱敏
+ case ID_CARD:
+ jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 3, 4));
+ break;
+ // 固定电话脱敏
+ case FIXED_PHONE:
+ jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
+ break;
+ // 手机号脱敏
+ case MOBILE_PHONE:
+ jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));
+ break;
+ // 地址脱敏
+ case ADDRESS:
+ jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));
+ break;
+ // 邮箱脱敏
+ case EMAIL:
+ jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));
+ break;
+ // 密码脱敏
+ case PASSWORD:
+ jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));
+ break;
+ // 中国车牌脱敏
+ case CAR_LICENSE:
+ jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));
+ break;
+ // 银行卡脱敏
+ case BANK_CARD:
+ jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));
+ break;
+ default:
+ }
+ }
+
+ @Override
+ public JsonSerializer> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
+ if (beanProperty != null) {
+ // 判断数据类型是否为String类型
+ if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
+ // 获取定义的注解
+ CoderDesensitize desensitize = beanProperty.getAnnotation(CoderDesensitize.class);
+ // 为null
+ if (desensitize == null) {
+ desensitize = beanProperty.getContextAnnotation(CoderDesensitize.class);
+ }
+ // 不为null
+ if (desensitize != null) {
+ // 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。
+ return new DesensitizeJsonSerializer(desensitize.rule(), desensitize.beginExclude(),
+ desensitize.endInclude());
+ }
+ }
+
+ return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
+ }
+ return serializerProvider.findNullValueSerializer(null);
+ }
+
+}
diff --git a/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/enums/DesensitizeRuleEnum.java b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/enums/DesensitizeRuleEnum.java
new file mode 100755
index 0000000..9d527ec
--- /dev/null
+++ b/heritage-plugins/heritage-desensitize/src/main/java/org/leocoder/heritage/desensitize/enums/DesensitizeRuleEnum.java
@@ -0,0 +1,67 @@
+package org.leocoder.heritage.desensitize.enums;
+
+import lombok.AllArgsConstructor;
+
+/**
+ * @author Leocoder
+ * @description [DesensitizeRuleEnum脱敏策略]
+ */
+@AllArgsConstructor
+public enum DesensitizeRuleEnum {
+
+ /**
+ * 自定义规则
+ */
+ CODER_RULE,
+
+ /**
+ * 用户id
+ */
+ USER_ID,
+
+ /**
+ * 中文名
+ */
+ CHINESE_NAME,
+
+ /**
+ * 身份证号
+ */
+ ID_CARD,
+
+ /**
+ * 固定电话(座机号)
+ */
+ FIXED_PHONE,
+
+ /**
+ * 手机号
+ */
+ MOBILE_PHONE,
+
+ /**
+ * 地址
+ */
+ ADDRESS,
+
+ /**
+ * 电子邮件
+ */
+ EMAIL,
+
+ /**
+ * 密码
+ */
+ PASSWORD,
+
+ /**
+ * 中国大陆车牌,包含普通车辆、新能源车辆
+ */
+ CAR_LICENSE,
+
+ /**
+ * 银行卡
+ */
+ BANK_CARD
+
+}
diff --git a/heritage-plugins/heritage-dict/pom.xml b/heritage-plugins/heritage-dict/pom.xml
new file mode 100644
index 0000000..97686a6
--- /dev/null
+++ b/heritage-plugins/heritage-dict/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+ org.leocoder.heritage
+ heritage-plugins
+ ${revision}
+
+
+ heritage-dict
+ heritage-dict
+ 字典翻译插件
+
+
+
+
+ org.leocoder.heritage
+ heritage-common
+ ${revision}
+
+
+
+ org.leocoder.heritage
+ heritage-model
+ ${revision}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
\ No newline at end of file
diff --git a/heritage-plugins/heritage-dict/src/main/java/org/leocoder/heritage/dict/anno/EnableCoderDict.java b/heritage-plugins/heritage-dict/src/main/java/org/leocoder/heritage/dict/anno/EnableCoderDict.java
new file mode 100644
index 0000000..1fba66b
--- /dev/null
+++ b/heritage-plugins/heritage-dict/src/main/java/org/leocoder/heritage/dict/anno/EnableCoderDict.java
@@ -0,0 +1,16 @@
+package org.leocoder.heritage.dict.anno;
+
+import org.leocoder.heritage.common.utils.cache.RedisUtil;
+import org.leocoder.heritage.dict.aspect.CoderDictAspect;
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+@Import({CoderDictAspect.class, RedisUtil.class})
+public @interface EnableCoderDict {
+
+}
\ No newline at end of file
diff --git a/heritage-plugins/heritage-dict/src/main/java/org/leocoder/heritage/dict/aspect/CoderDictAspect.java b/heritage-plugins/heritage-dict/src/main/java/org/leocoder/heritage/dict/aspect/CoderDictAspect.java
new file mode 100644
index 0000000..5f4a1cf
--- /dev/null
+++ b/heritage-plugins/heritage-dict/src/main/java/org/leocoder/heritage/dict/aspect/CoderDictAspect.java
@@ -0,0 +1,212 @@
+package org.leocoder.heritage.dict.aspect;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.leocoder.heritage.common.anno.CoderDict;
+import org.leocoder.heritage.common.anno.CoderDictClass;
+import org.leocoder.heritage.common.constants.CoderCacheConstants;
+import org.leocoder.heritage.common.utils.cache.RedisUtil;
+import org.leocoder.heritage.domain.pojo.system.SysDictData;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Leocoder
+ * @description [CoderDictAspect]
+ */
+@Aspect
+@Order(4)
+@Component
+@Slf4j
+public class CoderDictAspect {
+
+ private Map dictMap = new HashMap<>();
+
+ @Resource
+ private RedisUtil redisUtil;
+
+ @Pointcut("@annotation(org.leocoder.heritage.common.anno.CoderDictClass)")
+ public void logPointCut() {
+ }
+
+ /**
+ * @description [翻译数据]
+ * 需要处理的数据类型:
+ * 1、分页数据R>
+ * 2、普通列表R>
+ * 3、普通数据R
+ * @author Leocoder
+ */
+ @Around("@annotation(CoderDictClass)")
+ public Object CoderTypeDictTranslation(final ProceedingJoinPoint proceedingJoinPoint, CoderDictClass CoderDictClass) throws Throwable {
+ Object proceed = proceedingJoinPoint.proceed();
+ if (ObjectUtils.isEmpty(proceed)) {
+ return proceed;
+ }
+ if (proceed instanceof List) {
+ // 数据字典翻译
+ List