From 70b25718260b43f397291adca26ca8b45ceb0ab4 Mon Sep 17 00:00:00 2001
From: houzhongjian <houzhongyi@126.com>
Date: 星期四, 10 四月 2025 09:49:52 +0800
Subject: [PATCH] 1、移除wx、aliyun等第三方工具类 2、移除sms消息功能 3、移除iailab-framework框架依赖,将其单独提取出来 4、网关增加ansteel和shangangrizhao

---
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthService.java               |   23 -
 iailab-module-system/iailab-module-system-biz/src/main/resources/application-dev.yaml                                                 |   11 
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/auth/AuthConvert.java                    |    6 
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthServiceImpl.java           |   58 ---
 iailab-plat-sdk/src/main/java/com/iailab/sdk/auth/client/IailabClient.java                                                            |    2 
 pom.xml                                                                                                                               |  655 ++++++++++++++++-----------------
 /dev/null                                                                                                                             |  173 ---------
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/user/UserConvert.java                    |    4 
 iailab-cloud/iailab-gateway/src/main/resources/application.yaml                                                                       |    7 
 iailab-module-system/iailab-module-system-biz/pom.xml                                                                                 |   94 +++-
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java        |   49 --
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/rpc/config/RpcConfiguration.java       |    3 
 iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/user/UserProfileController.java |    8 
 iailab-module-system/iailab-module-system-biz/src/main/resources/application.yaml                                                     |   11 
 14 files changed, 415 insertions(+), 689 deletions(-)

diff --git a/iailab-cloud/iailab-gateway/src/main/resources/application.yaml b/iailab-cloud/iailab-gateway/src/main/resources/application.yaml
index 4ecec4f..02f0004 100644
--- a/iailab-cloud/iailab-gateway/src/main/resources/application.yaml
+++ b/iailab-cloud/iailab-gateway/src/main/resources/application.yaml
@@ -150,6 +150,13 @@
             - Path=/admin-api/xmcsms/**
           filters:
             - RewritePath=/admin-api/xmcsms/v3/api-docs, /v3/api-docs
+        ## shangangrizhao 服务
+        - id: shangangrizhao-admin-api # 路由的编号
+          uri: grayLb://shangangrizhao-server
+          predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
+            - Path=/admin-api/shangangrizhao/**
+          filters:
+            - RewritePath=/admin-api/shangangrizhao/v3/api-docs, /v3/api-docs
       x-forwarded:
         prefix-enabled: true # 避免 Swagger 重复带上额外的 /admin-api/system 前缀
 
diff --git a/iailab-framework/iailab-common-biz-data-permission/pom.xml b/iailab-framework/iailab-common-biz-data-permission/pom.xml
deleted file mode 100644
index 2fd16fe..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/pom.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>iailab-framework</artifactId>
-        <groupId>com.iailab</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-biz-data-permission</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>数据权限</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-security</artifactId>
-            <optional>true</optional> <!-- 可选,如果使用 DeptDataPermissionRule 必须提供 -->
-        </dependency>
-
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-mybatis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-        </dependency>
-
-        <!-- RPC 远程调用相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-rpc</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- 业务组件 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-module-system-api</artifactId> <!-- 需要使用它,进行数据权限的获取 -->
-            <version>${revision}</version>
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionAutoConfiguration.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionAutoConfiguration.java
deleted file mode 100644
index 7428e3c..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionAutoConfiguration.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.iailab.framework.datapermission.config;
-
-import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
-import com.iailab.framework.datapermission.core.aop.DataPermissionAnnotationAdvisor;
-import com.iailab.framework.datapermission.core.db.DataPermissionRuleHandler;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRule;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRuleFactory;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRuleFactoryImpl;
-import com.iailab.framework.mybatis.core.util.MyBatisUtils;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-
-import java.util.List;
-
-/**
- * 数据权限的自动配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-public class IailabDataPermissionAutoConfiguration {
-
-    @Bean
-    public DataPermissionRuleFactory dataPermissionRuleFactory(List<DataPermissionRule> rules) {
-        return new DataPermissionRuleFactoryImpl(rules);
-    }
-
-    @Bean
-    public DataPermissionRuleHandler dataPermissionRuleHandler(MybatisPlusInterceptor interceptor,
-                                                               DataPermissionRuleFactory ruleFactory) {
-        // 创建 DataPermissionInterceptor 拦截器
-        DataPermissionRuleHandler handler = new DataPermissionRuleHandler(ruleFactory);
-        DataPermissionInterceptor inner = new DataPermissionInterceptor(handler);
-        // 添加到 interceptor 中
-        // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
-        MyBatisUtils.addInterceptor(interceptor, inner, 0);
-        return handler;
-    }
-
-
-    @Bean
-    public DataPermissionAnnotationAdvisor dataPermissionAnnotationAdvisor() {
-        return new DataPermissionAnnotationAdvisor();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionRpcAutoConfiguration.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionRpcAutoConfiguration.java
deleted file mode 100644
index e4ba244..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDataPermissionRpcAutoConfiguration.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.datapermission.config;
-
-import com.iailab.framework.datapermission.core.rpc.DataPermissionRequestInterceptor;
-import com.iailab.framework.datapermission.core.rpc.DataPermissionRpcWebFilter;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-
-import static com.iailab.framework.common.enums.WebFilterOrderEnum.TENANT_CONTEXT_FILTER;
-
-
-/**
- * 数据权限针对 RPC 的自动配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-@ConditionalOnClass(name = "feign.RequestInterceptor")
-public class IailabDataPermissionRpcAutoConfiguration {
-
-    @Bean
-    public DataPermissionRequestInterceptor dataPermissionRequestInterceptor() {
-        return new DataPermissionRequestInterceptor();
-    }
-
-    @Bean
-    public FilterRegistrationBean<DataPermissionRpcWebFilter> dataPermissionRpcFilter() {
-        FilterRegistrationBean<DataPermissionRpcWebFilter> registrationBean = new FilterRegistrationBean<>();
-        registrationBean.setFilter(new DataPermissionRpcWebFilter());
-        registrationBean.setOrder(TENANT_CONTEXT_FILTER - 1); // 顺序没有绝对的要求,在租户 Filter 前面稳妥点
-        return registrationBean;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDeptDataPermissionAutoConfiguration.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDeptDataPermissionAutoConfiguration.java
deleted file mode 100644
index a591f11..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/config/IailabDeptDataPermissionAutoConfiguration.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.iailab.framework.datapermission.config;
-
-import cn.hutool.extra.spring.SpringUtil;
-import com.iailab.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
-import com.iailab.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.module.system.api.permission.PermissionApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.context.annotation.Bean;
-
-import java.util.List;
-
-/**
- * 基于部门的数据权限 AutoConfiguration
- *
- * @author iailab
- */
-@AutoConfiguration
-@ConditionalOnClass(LoginUser.class)
-@ConditionalOnBean(value = DeptDataPermissionRuleCustomizer.class)
-public class IailabDeptDataPermissionAutoConfiguration {
-
-    @Bean
-    public DeptDataPermissionRule deptDataPermissionRule(PermissionApi permissionApi,
-                                                         List<DeptDataPermissionRuleCustomizer> customizers) {
-        // Cloud 专属逻辑:优先使用本地的 PermissionApi 实现类,而不是 Feign 调用
-        // 原因:在创建租户时,租户还没创建好,导致 Feign 调用获取数据权限时,报“租户不存在”的错误
-        try {
-            PermissionApi permissionApiImpl = SpringUtil.getBean("permissionApiImpl", PermissionApi.class);
-            if (permissionApiImpl != null) {
-                permissionApi = permissionApiImpl;
-            }
-        } catch (Exception ignored) {}
-
-        // 创建 DeptDataPermissionRule 对象
-        DeptDataPermissionRule rule = new DeptDataPermissionRule(permissionApi);
-        // 补全表配置
-        customizers.forEach(customizer -> customizer.customize(rule));
-        return rule;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/annotation/DataPermission.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/annotation/DataPermission.java
deleted file mode 100644
index 65f8cd5..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/annotation/DataPermission.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.datapermission.core.annotation;
-
-import com.iailab.framework.datapermission.core.rule.DataPermissionRule;
-
-import java.lang.annotation.*;
-
-/**
- * 数据权限注解
- * 可声明在类或者方法上,标识使用的数据权限规则
- *
- * @author iailab
- */
-@Target({ElementType.TYPE, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface DataPermission {
-
-    /**
-     * 当前类或方法是否开启数据权限
-     * 即使不添加 @DataPermission 注解,默认是开启状态
-     * 可通过设置 enable 为 false 禁用
-     */
-    boolean enable() default true;
-
-    /**
-     * 生效的数据权限规则数组,优先级高于 {@link #excludeRules()}
-     */
-    Class<? extends DataPermissionRule>[] includeRules() default {};
-
-    /**
-     * 排除的数据权限规则数组,优先级最低
-     */
-    Class<? extends DataPermissionRule>[] excludeRules() default {};
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationAdvisor.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationAdvisor.java
deleted file mode 100644
index 80308c4..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationAdvisor.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.datapermission.core.aop;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import org.aopalliance.aop.Advice;
-import org.springframework.aop.Pointcut;
-import org.springframework.aop.support.AbstractPointcutAdvisor;
-import org.springframework.aop.support.ComposablePointcut;
-import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
-
-/**
- * {@link com.iailab.framework.datapermission.core.annotation.DataPermission} 注解的 Advisor 实现类
- *
- * @author iailab
- */
-@Getter
-@EqualsAndHashCode(callSuper = true)
-public class DataPermissionAnnotationAdvisor extends AbstractPointcutAdvisor {
-
-    private final Advice advice;
-
-    private final Pointcut pointcut;
-
-    public DataPermissionAnnotationAdvisor() {
-        this.advice = new DataPermissionAnnotationInterceptor();
-        this.pointcut = this.buildPointcut();
-    }
-
-    protected Pointcut buildPointcut() {
-        Pointcut classPointcut = new AnnotationMatchingPointcut(DataPermission.class, true);
-        Pointcut methodPointcut = new AnnotationMatchingPointcut(null, DataPermission.class, true);
-        return new ComposablePointcut(classPointcut).union(methodPointcut);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationInterceptor.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationInterceptor.java
deleted file mode 100644
index 2e9726a..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationInterceptor.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.iailab.framework.datapermission.core.aop;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import lombok.Getter;
-import org.aopalliance.intercept.MethodInterceptor;
-import org.aopalliance.intercept.MethodInvocation;
-import org.springframework.core.MethodClassKey;
-import org.springframework.core.annotation.AnnotationUtils;
-
-import java.lang.reflect.Method;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * {@link DataPermission} 注解的拦截器
- * 1. 在执行方法前,将 @DataPermission 注解入栈
- * 2. 在执行方法后,将 @DataPermission 注解出栈
- *
- * @author iailab
- */
-@DataPermission // 该注解,用于 {@link DATA_PERMISSION_NULL} 的空对象
-public class DataPermissionAnnotationInterceptor implements MethodInterceptor {
-
-    /**
-     * DataPermission 空对象,用于方法无 {@link DataPermission} 注解时,使用 DATA_PERMISSION_NULL 进行占位
-     */
-    static final DataPermission DATA_PERMISSION_NULL = DataPermissionAnnotationInterceptor.class.getAnnotation(DataPermission.class);
-
-    @Getter
-    private final Map<MethodClassKey, DataPermission> dataPermissionCache = new ConcurrentHashMap<>();
-
-    @Override
-    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
-        // 入栈
-        DataPermission dataPermission = this.findAnnotation(methodInvocation);
-        if (dataPermission != null) {
-            DataPermissionContextHolder.add(dataPermission);
-        }
-        try {
-            // 执行逻辑
-            return methodInvocation.proceed();
-        } finally {
-            // 出栈
-            if (dataPermission != null) {
-                DataPermissionContextHolder.remove();
-            }
-        }
-    }
-
-    private DataPermission findAnnotation(MethodInvocation methodInvocation) {
-        // 1. 从缓存中获取
-        Method method = methodInvocation.getMethod();
-        Object targetObject = methodInvocation.getThis();
-        Class<?> clazz = targetObject != null ? targetObject.getClass() : method.getDeclaringClass();
-        MethodClassKey methodClassKey = new MethodClassKey(method, clazz);
-        DataPermission dataPermission = dataPermissionCache.get(methodClassKey);
-        if (dataPermission != null) {
-            return dataPermission != DATA_PERMISSION_NULL ? dataPermission : null;
-        }
-
-        // 2.1 从方法中获取
-        dataPermission = AnnotationUtils.findAnnotation(method, DataPermission.class);
-        // 2.2 从类上获取
-        if (dataPermission == null) {
-            dataPermission = AnnotationUtils.findAnnotation(clazz, DataPermission.class);
-        }
-        // 2.3 添加到缓存中
-        dataPermissionCache.put(methodClassKey, dataPermission != null ? dataPermission : DATA_PERMISSION_NULL);
-        return dataPermission;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionContextHolder.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionContextHolder.java
deleted file mode 100644
index c7cdbb3..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/aop/DataPermissionContextHolder.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.iailab.framework.datapermission.core.aop;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.alibaba.ttl.TransmittableThreadLocal;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * {@link DataPermission} 注解的 Context 上下文
- *
- * @author iailab
- */
-public class DataPermissionContextHolder {
-
-    /**
-     * 使用 List 的原因,可能存在方法的嵌套调用
-     */
-    private static final ThreadLocal<LinkedList<DataPermission>> DATA_PERMISSIONS =
-            TransmittableThreadLocal.withInitial(LinkedList::new);
-
-    /**
-     * 获得当前的 DataPermission 注解
-     *
-     * @return DataPermission 注解
-     */
-    public static DataPermission get() {
-        return DATA_PERMISSIONS.get().peekLast();
-    }
-
-    /**
-     * 入栈 DataPermission 注解
-     *
-     * @param dataPermission DataPermission 注解
-     */
-    public static void add(DataPermission dataPermission) {
-        DATA_PERMISSIONS.get().addLast(dataPermission);
-    }
-
-    /**
-     * 出栈 DataPermission 注解
-     *
-     * @return DataPermission 注解
-     */
-    public static DataPermission remove() {
-        DataPermission dataPermission = DATA_PERMISSIONS.get().removeLast();
-        // 无元素时,清空 ThreadLocal
-        if (DATA_PERMISSIONS.get().isEmpty()) {
-            DATA_PERMISSIONS.remove();
-        }
-        return dataPermission;
-    }
-
-    /**
-     * 获得所有 DataPermission
-     *
-     * @return DataPermission 队列
-     */
-    public static List<DataPermission> getAll() {
-        return DATA_PERMISSIONS.get();
-    }
-
-    /**
-     * 清空上下文
-     *
-     * 目前仅仅用于单测
-     */
-    public static void clear() {
-        DATA_PERMISSIONS.remove();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/db/DataPermissionRuleHandler.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/db/DataPermissionRuleHandler.java
deleted file mode 100644
index b341ad9..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/db/DataPermissionRuleHandler.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.iailab.framework.datapermission.core.db;
-
-import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRule;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRuleFactory;
-import com.iailab.framework.mybatis.core.util.MyBatisUtils;
-import lombok.RequiredArgsConstructor;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
-import net.sf.jsqlparser.schema.Table;
-
-import java.util.List;
-
-/**
- * 基于 {@link DataPermissionRule} 的数据权限处理器
- *
- * 它的底层,是基于 MyBatis Plus 的 <a href="https://baomidou.com/plugins/data-permission/">数据权限插件</a>
- * 核心原理:它会在 SQL 执行前拦截 SQL 语句,并根据用户权限动态添加权限相关的 SQL 片段。这样,只有用户有权限访问的数据才会被查询出来
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
-
-    private final DataPermissionRuleFactory ruleFactory;
-
-    @Override
-    public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
-        // 获得 Mapper 对应的数据权限的规则
-        List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(mappedStatementId);
-        if (CollUtil.isEmpty(rules)) {
-            return null;
-        }
-
-        // 生成条件
-        Expression allExpression = null;
-        for (DataPermissionRule rule : rules) {
-            // 判断表名是否匹配
-            String tableName = MyBatisUtils.getTableName(table);
-            if (!rule.getTableNames().contains(tableName)) {
-                continue;
-            }
-
-            // 单条规则的条件
-            Expression oneExpress = rule.getExpression(tableName, table.getAlias());
-            if (oneExpress == null) {
-                continue;
-            }
-            // 拼接到 allExpression 中
-            allExpression = allExpression == null ? oneExpress
-                    : new AndExpression(allExpression, oneExpress);
-        }
-        return allExpression;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rpc/DataPermissionRequestInterceptor.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rpc/DataPermissionRequestInterceptor.java
deleted file mode 100644
index 6969a45..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rpc/DataPermissionRequestInterceptor.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.datapermission.core.rpc;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.iailab.framework.datapermission.core.aop.DataPermissionContextHolder;
-import feign.RequestInterceptor;
-import feign.RequestTemplate;
-
-/**
- * DataPermission 的 RequestInterceptor 实现类:Feign 请求时,将 {@link DataPermission} 设置到 header 中,继续透传给被调用的服务
- *
- * 注意:由于 {@link DataPermission} 不支持序列化和反序列化,所以暂时只能传递它的 enable 属性
- *
- * @author iailab
- */
-public class DataPermissionRequestInterceptor implements RequestInterceptor {
-
-    public static final String ENABLE_HEADER_NAME = "data-permission-enable";
-
-    @Override
-    public void apply(RequestTemplate requestTemplate) {
-        DataPermission dataPermission = DataPermissionContextHolder.get();
-        if (dataPermission != null && Boolean.FALSE.equals(dataPermission.enable())) {
-            requestTemplate.header(ENABLE_HEADER_NAME, "false");
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rpc/DataPermissionRpcWebFilter.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rpc/DataPermissionRpcWebFilter.java
deleted file mode 100644
index 8a4bb79..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rpc/DataPermissionRpcWebFilter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.datapermission.core.rpc;
-
-import com.iailab.framework.datapermission.core.util.DataPermissionUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * 针对 {@link DataPermissionRequestInterceptor} 的 RPC 调用,设置 {@link com.iailab.framework.datapermission.core.aop.DataPermissionContextHolder} 的上下文
- *
- * @author iailab
- */
-public class DataPermissionRpcWebFilter extends OncePerRequestFilter {
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        String enable = request.getHeader(DataPermissionRequestInterceptor.ENABLE_HEADER_NAME);
-        if (Objects.equals(enable, Boolean.FALSE.toString())) {
-            DataPermissionUtils.executeIgnore(() -> {
-                try {
-                    chain.doFilter(request, response);
-                } catch (IOException | ServletException e) {
-                    throw new RuntimeException(e);
-                }
-            });
-        } else {
-            chain.doFilter(request, response);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRule.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRule.java
deleted file mode 100644
index 9b45315..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRule.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.datapermission.core.rule;
-
-import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import net.sf.jsqlparser.expression.Alias;
-import net.sf.jsqlparser.expression.Expression;
-
-import java.util.Set;
-
-/**
- * 数据权限规则接口
- * 通过实现接口,自定义数据规则。例如说,
- *
- * @author iailab
- */
-public interface DataPermissionRule {
-
-    /**
-     * 返回需要生效的表名数组
-     * 为什么需要该方法?Data Permission 数组基于 SQL 重写,通过 Where 返回只有权限的数据
-     *
-     * 如果需要基于实体名获得表名,可调用 {@link TableInfoHelper#getTableInfo(Class)} 获得
-     *
-     * @return 表名数组
-     */
-    Set<String> getTableNames();
-
-    /**
-     * 根据表名和别名,生成对应的 WHERE / OR 过滤条件
-     *
-     * @param tableName 表名
-     * @param tableAlias 别名,可能为空
-     * @return 过滤条件 Expression 表达式
-     */
-    Expression getExpression(String tableName, Alias tableAlias);
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactory.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactory.java
deleted file mode 100644
index 48ebf78..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactory.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.datapermission.core.rule;
-
-import java.util.List;
-
-/**
- * {@link DataPermissionRule} 工厂接口
- * 作为 {@link DataPermissionRule} 的容器,提供管理能力
- *
- * @author iailab
- */
-public interface DataPermissionRuleFactory {
-
-    /**
-     * 获得所有数据权限规则数组
-     *
-     * @return 数据权限规则数组
-     */
-    List<DataPermissionRule> getDataPermissionRules();
-
-    /**
-     * 获得指定 Mapper 的数据权限规则数组
-     *
-     * @param mappedStatementId 指定 Mapper 的编号
-     * @return 数据权限规则数组
-     */
-    List<DataPermissionRule> getDataPermissionRule(String mappedStatementId);
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java
deleted file mode 100644
index 7ebe9db..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.iailab.framework.datapermission.core.rule;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.iailab.framework.datapermission.core.aop.DataPermissionContextHolder;
-import lombok.RequiredArgsConstructor;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 默认的 DataPermissionRuleFactoryImpl 实现类
- * 支持通过 {@link DataPermissionContextHolder} 过滤数据权限
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory {
-
-    /**
-     * 数据权限规则数组
-     */
-    private final List<DataPermissionRule> rules;
-
-    @Override
-    public List<DataPermissionRule> getDataPermissionRules() {
-        return rules;
-    }
-
-    @Override // mappedStatementId 参数,暂时没有用。以后,可以基于 mappedStatementId + DataPermission 进行缓存
-    public List<DataPermissionRule> getDataPermissionRule(String mappedStatementId) {
-        // 1. 无数据权限
-        if (CollUtil.isEmpty(rules)) {
-            return Collections.emptyList();
-        }
-        // 2. 未配置,则默认开启
-        DataPermission dataPermission = DataPermissionContextHolder.get();
-        if (dataPermission == null) {
-            return rules;
-        }
-        // 3. 已配置,但禁用
-        if (!dataPermission.enable()) {
-            return Collections.emptyList();
-        }
-
-        // 4. 已配置,只选择部分规则
-        if (ArrayUtil.isNotEmpty(dataPermission.includeRules())) {
-            return rules.stream().filter(rule -> ArrayUtil.contains(dataPermission.includeRules(), rule.getClass()))
-                    .collect(Collectors.toList()); // 一般规则不会太多,所以不采用 HashSet 查询
-        }
-        // 5. 已配置,只排除部分规则
-        if (ArrayUtil.isNotEmpty(dataPermission.excludeRules())) {
-            return rules.stream().filter(rule -> !ArrayUtil.contains(dataPermission.excludeRules(), rule.getClass()))
-                    .collect(Collectors.toList()); // 一般规则不会太多,所以不采用 HashSet 查询
-        }
-        // 6. 已配置,全部规则
-        return rules;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java
deleted file mode 100644
index 409d01d..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package com.iailab.framework.datapermission.core.rule.dept;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.util.collection.CollectionUtils;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRule;
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.iailab.framework.mybatis.core.util.MyBatisUtils;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.module.system.api.permission.PermissionApi;
-import com.iailab.module.system.api.permission.dto.DeptDataPermissionRespDTO;
-import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import net.sf.jsqlparser.expression.*;
-import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
-import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
-import net.sf.jsqlparser.expression.operators.relational.InExpression;
-import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * 基于部门的 {@link DataPermissionRule} 数据权限规则实现
- *
- * 注意,使用 DeptDataPermissionRule 时,需要保证表中有 dept_id 部门编号的字段,可自定义。
- *
- * 实际业务场景下,会存在一个经典的问题?当用户修改部门时,冗余的 dept_id 是否需要修改?
- * 1. 一般情况下,dept_id 不进行修改,则会导致用户看不到之前的数据。【iailab-server 采用该方案】
- * 2. 部分情况下,希望该用户还是能看到之前的数据,则有两种方式解决:【需要你改造该 DeptDataPermissionRule 的实现代码】
- *  1)编写洗数据的脚本,将 dept_id 修改成新部门的编号;【建议】
- *      最终过滤条件是 WHERE dept_id = ?
- *  2)洗数据的话,可能涉及的数据量较大,也可以采用 user_id 进行过滤的方式,此时需要获取到 dept_id 对应的所有 user_id 用户编号;
- *      最终过滤条件是 WHERE user_id IN (?, ?, ? ...)
- *  3)想要保证原 dept_id 和 user_id 都可以看的到,此时使用 dept_id 和 user_id 一起过滤;
- *      最终过滤条件是 WHERE dept_id = ? OR user_id IN (?, ?, ? ...)
- *
- * @author iailab
- */
-@AllArgsConstructor
-@Slf4j
-public class DeptDataPermissionRule implements DataPermissionRule {
-
-    /**
-     * LoginUser 的 Context 缓存 Key
-     */
-    protected static final String CONTEXT_KEY = DeptDataPermissionRule.class.getSimpleName();
-
-    private static final String DEPT_COLUMN_NAME = "dept_id";
-    private static final String USER_COLUMN_NAME = "user_id";
-
-    static final Expression EXPRESSION_NULL = new NullValue();
-
-    private final PermissionApi permissionApi;
-
-    /**
-     * 基于部门的表字段配置
-     * 一般情况下,每个表的部门编号字段是 dept_id,通过该配置自定义。
-     *
-     * key:表名
-     * value:字段名
-     */
-    private final Map<String, String> deptColumns = new HashMap<>();
-    /**
-     * 基于用户的表字段配置
-     * 一般情况下,每个表的部门编号字段是 dept_id,通过该配置自定义。
-     *
-     * key:表名
-     * value:字段名
-     */
-    private final Map<String, String> userColumns = new HashMap<>();
-    /**
-     * 所有表名,是 {@link #deptColumns} 和 {@link #userColumns} 的合集
-     */
-    private final Set<String> TABLE_NAMES = new HashSet<>();
-
-    @Override
-    public Set<String> getTableNames() {
-        return TABLE_NAMES;
-    }
-
-    @Override
-    public Expression getExpression(String tableName, Alias tableAlias) {
-        // 只有有登陆用户的情况下,才进行数据权限的处理
-        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
-        if (loginUser == null) {
-            return null;
-        }
-        // 只有管理员类型的用户,才进行数据权限的处理
-        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
-            return null;
-        }
-
-        // 获得数据权限
-        DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
-        // 从上下文中拿不到,则调用逻辑进行获取
-        if (deptDataPermission == null) {
-            deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()).getCheckedData();
-            if (deptDataPermission == null) {
-                log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
-                throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
-                        loginUser.getId(), tableName, tableAlias.getName()));
-            }
-            // 添加到上下文中,避免重复计算
-            loginUser.setContext(CONTEXT_KEY, deptDataPermission);
-        }
-
-        // 情况一,如果是 ALL 可查看全部,则无需拼接条件
-        if (deptDataPermission.getAll()) {
-            return null;
-        }
-
-        // 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限
-        if (CollUtil.isEmpty(deptDataPermission.getDeptIds())
-                && Boolean.FALSE.equals(deptDataPermission.getSelf())) {
-            return new EqualsTo(null, null); // WHERE null = null,可以保证返回的数据为空
-        }
-
-        // 情况三,拼接 Dept 和 User 的条件,最后组合
-        Expression deptExpression = buildDeptExpression(tableName,tableAlias, deptDataPermission.getDeptIds());
-        Expression userExpression = buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), loginUser.getId());
-        if (deptExpression == null && userExpression == null) {
-            // TODO iailab:获得不到条件的时候,暂时不抛出异常,而是不返回数据
-            log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
-                    JsonUtils.toJsonString(loginUser), tableName, tableAlias, JsonUtils.toJsonString(deptDataPermission));
-//            throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 构建的条件为空",
-//                    loginUser.getId(), tableName, tableAlias.getName()));
-            return EXPRESSION_NULL;
-        }
-        if (deptExpression == null) {
-            return userExpression;
-        }
-        if (userExpression == null) {
-            return deptExpression;
-        }
-        // 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE (dept_id IN ? OR user_id = ?)
-        return new ParenthesedExpressionList(new OrExpression(deptExpression, userExpression));
-    }
-
-    private Expression buildDeptExpression(String tableName, Alias tableAlias, Set<Long> deptIds) {
-        // 如果不存在配置,则无需作为条件
-        String columnName = deptColumns.get(tableName);
-        if (StrUtil.isEmpty(columnName)) {
-            return null;
-        }
-        // 如果为空,则无条件
-        if (CollUtil.isEmpty(deptIds)) {
-            return null;
-        }
-        // 拼接条件
-        return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
-                // Parenthesis 的目的,是提供 (1,2,3) 的 () 左右括号
-                new ParenthesedExpressionList(new ExpressionList<LongValue>(CollectionUtils.convertList(deptIds, LongValue::new))));
-    }
-
-    private Expression buildUserExpression(String tableName, Alias tableAlias, Boolean self, Long userId) {
-        // 如果不查看自己,则无需作为条件
-        if (Boolean.FALSE.equals(self)) {
-            return null;
-        }
-        String columnName = userColumns.get(tableName);
-        if (StrUtil.isEmpty(columnName)) {
-            return null;
-        }
-        // 拼接条件
-        return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), new LongValue(userId));
-    }
-
-    // ==================== 添加配置 ====================
-
-    public void addDeptColumn(Class<? extends BaseDO> entityClass) {
-        addDeptColumn(entityClass, DEPT_COLUMN_NAME);
-    }
-
-    public void addDeptColumn(Class<? extends BaseDO> entityClass, String columnName) {
-        String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
-        addDeptColumn(tableName, columnName);
-    }
-
-    public void addDeptColumn(String tableName, String columnName) {
-        deptColumns.put(tableName, columnName);
-        TABLE_NAMES.add(tableName);
-    }
-
-    public void addUserColumn(Class<? extends BaseDO> entityClass) {
-        addUserColumn(entityClass, USER_COLUMN_NAME);
-    }
-
-    public void addUserColumn(Class<? extends BaseDO> entityClass, String columnName) {
-        String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
-        addUserColumn(tableName, columnName);
-    }
-
-    public void addUserColumn(String tableName, String columnName) {
-        userColumns.put(tableName, columnName);
-        TABLE_NAMES.add(tableName);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java
deleted file mode 100644
index b8a1947..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRuleCustomizer.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.iailab.framework.datapermission.core.rule.dept;
-
-/**
- * {@link DeptDataPermissionRule} 的自定义配置接口
- *
- * @author iailab
- */
-@FunctionalInterface
-public interface DeptDataPermissionRuleCustomizer {
-
-    /**
-     * 自定义该权限规则
-     * 1. 调用 {@link DeptDataPermissionRule#addDeptColumn(Class, String)} 方法,配置基于 dept_id 的过滤规则
-     * 2. 调用 {@link DeptDataPermissionRule#addUserColumn(Class, String)} 方法,配置基于 user_id 的过滤规则
-     *
-     * @param rule 权限规则
-     */
-    void customize(DeptDataPermissionRule rule);
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/package-info.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/package-info.java
deleted file mode 100644
index cb10588..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/rule/dept/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 基于部门的数据权限规则
- *
- * @author iailab
- */
-package com.iailab.framework.datapermission.core.rule.dept;
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/util/DataPermissionUtils.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/util/DataPermissionUtils.java
deleted file mode 100644
index a4a5ffc..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/core/util/DataPermissionUtils.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.iailab.framework.datapermission.core.util;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.iailab.framework.datapermission.core.aop.DataPermissionContextHolder;
-import lombok.SneakyThrows;
-
-import java.util.concurrent.Callable;
-
-/**
- * 数据权限 Util
- *
- * @author iailab
- */
-public class DataPermissionUtils {
-
-    private static DataPermission DATA_PERMISSION_DISABLE;
-
-    @DataPermission(enable = false)
-    @SneakyThrows
-    private static DataPermission getDisableDataPermissionDisable() {
-        if (DATA_PERMISSION_DISABLE == null) {
-            DATA_PERMISSION_DISABLE = DataPermissionUtils.class
-                    .getDeclaredMethod("getDisableDataPermissionDisable")
-                    .getAnnotation(DataPermission.class);
-        }
-        return DATA_PERMISSION_DISABLE;
-    }
-
-    /**
-     * 忽略数据权限,执行对应的逻辑
-     *
-     * @param runnable 逻辑
-     */
-    public static void executeIgnore(Runnable runnable) {
-        DataPermission dataPermission = getDisableDataPermissionDisable();
-        DataPermissionContextHolder.add(dataPermission);
-        try {
-            // 执行 runnable
-            runnable.run();
-        } finally {
-            DataPermissionContextHolder.remove();
-        }
-    }
-
-    /**
-     * 忽略数据权限,执行对应的逻辑
-     *
-     * @param callable 逻辑
-     * @return 执行结果
-     */
-    @SneakyThrows
-    public static <T> T executeIgnore(Callable<T> callable) {
-        DataPermission dataPermission = getDisableDataPermissionDisable();
-        DataPermissionContextHolder.add(dataPermission);
-        try {
-            // 执行 callable
-            return callable.call();
-        } finally {
-            DataPermissionContextHolder.remove();
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/package-info.java b/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/package-info.java
deleted file mode 100644
index afd94ed..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/java/com/iailab/framework/datapermission/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 基于 JSqlParser 解析 SQL,增加数据权限的 WHERE 条件
- */
-package com.iailab.framework.datapermission;
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-biz-data-permission/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 5499998..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,3 +0,0 @@
-com.iailab.framework.datapermission.config.IailabDataPermissionAutoConfiguration
-com.iailab.framework.datapermission.config.IailabDeptDataPermissionAutoConfiguration
-com.iailab.framework.datapermission.config.IailabDataPermissionRpcAutoConfiguration
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java b/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java
deleted file mode 100644
index aa28b86..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.iailab.framework.datapermission.core.aop;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import org.aopalliance.intercept.MethodInvocation;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.lang.reflect.Method;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link DataPermissionAnnotationInterceptor} 的单元测试
- *
- * @author iailab
- */
-public class DataPermissionAnnotationInterceptorTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private DataPermissionAnnotationInterceptor interceptor;
-
-    @Mock
-    private MethodInvocation methodInvocation;
-
-    @BeforeEach
-    public void setUp() {
-        interceptor.getDataPermissionCache().clear();
-    }
-
-    @Test // 无 @DataPermission 注解
-    public void testInvoke_none() throws Throwable {
-        // 参数
-        mockMethodInvocation(TestNone.class);
-
-        // 调用
-        Object result = interceptor.invoke(methodInvocation);
-        // 断言
-        assertEquals("none", result);
-        assertEquals(1, interceptor.getDataPermissionCache().size());
-        assertTrue(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable());
-    }
-
-    @Test // 在 Method 上有 @DataPermission 注解
-    public void testInvoke_method() throws Throwable {
-        // 参数
-        mockMethodInvocation(TestMethod.class);
-
-        // 调用
-        Object result = interceptor.invoke(methodInvocation);
-        // 断言
-        assertEquals("method", result);
-        assertEquals(1, interceptor.getDataPermissionCache().size());
-        assertFalse(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable());
-    }
-
-    @Test // 在 Class 上有 @DataPermission 注解
-    public void testInvoke_class() throws Throwable {
-        // 参数
-        mockMethodInvocation(TestClass.class);
-
-        // 调用
-        Object result = interceptor.invoke(methodInvocation);
-        // 断言
-        assertEquals("class", result);
-        assertEquals(1, interceptor.getDataPermissionCache().size());
-        assertFalse(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable());
-    }
-
-    private void mockMethodInvocation(Class<?> clazz) throws Throwable {
-        Object targetObject = clazz.newInstance();
-        Method method = targetObject.getClass().getMethod("echo");
-        when(methodInvocation.getThis()).thenReturn(targetObject);
-        when(methodInvocation.getMethod()).thenReturn(method);
-        when(methodInvocation.proceed()).then(invocationOnMock -> method.invoke(targetObject));
-    }
-
-    static class TestMethod {
-
-        @DataPermission(enable = false)
-        public String echo() {
-            return "method";
-        }
-
-    }
-
-    @DataPermission(enable = false)
-    static class TestClass {
-
-        public String echo() {
-            return "class";
-        }
-
-    }
-
-    static class TestNone {
-
-        public String echo() {
-            return "none";
-        }
-
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/aop/DataPermissionContextHolderTest.java b/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/aop/DataPermissionContextHolderTest.java
deleted file mode 100644
index d3c1308..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/aop/DataPermissionContextHolderTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.iailab.framework.datapermission.core.aop;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.mockito.Mockito.mock;
-
-/**
- * {@link DataPermissionContextHolder} 的单元测试
- *
- * @author iailab
- */
-class DataPermissionContextHolderTest {
-
-    @BeforeEach
-    public void setUp() {
-        DataPermissionContextHolder.clear();
-    }
-
-    @Test
-    public void testGet() {
-        // mock 方法
-        DataPermission dataPermission01 = mock(DataPermission.class);
-        DataPermissionContextHolder.add(dataPermission01);
-        DataPermission dataPermission02 = mock(DataPermission.class);
-        DataPermissionContextHolder.add(dataPermission02);
-
-        // 调用
-        DataPermission result = DataPermissionContextHolder.get();
-        // 断言
-        assertSame(result, dataPermission02);
-    }
-
-    @Test
-    public void testPush() {
-        // 调用
-        DataPermission dataPermission01 = mock(DataPermission.class);
-        DataPermissionContextHolder.add(dataPermission01);
-        DataPermission dataPermission02 = mock(DataPermission.class);
-        DataPermissionContextHolder.add(dataPermission02);
-        // 断言
-        DataPermission first = DataPermissionContextHolder.getAll().get(0);
-        DataPermission second = DataPermissionContextHolder.getAll().get(1);
-        assertSame(dataPermission01, first);
-        assertSame(dataPermission02, second);
-    }
-
-    @Test
-    public void testRemove() {
-        // mock 方法
-        DataPermission dataPermission01 = mock(DataPermission.class);
-        DataPermissionContextHolder.add(dataPermission01);
-        DataPermission dataPermission02 = mock(DataPermission.class);
-        DataPermissionContextHolder.add(dataPermission02);
-
-        // 调用
-        DataPermission result = DataPermissionContextHolder.remove();
-        // 断言
-        assertSame(result, dataPermission02);
-        assertEquals(1, DataPermissionContextHolder.getAll().size());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java b/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java
deleted file mode 100644
index 555ae24..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java
+++ /dev/null
@@ -1,540 +0,0 @@
-package com.iailab.framework.datapermission.core.db;
-
-import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRule;
-import com.iailab.framework.datapermission.core.rule.DataPermissionRuleFactory;
-import com.iailab.framework.mybatis.core.util.MyBatisUtils;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import net.sf.jsqlparser.expression.Alias;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.LongValue;
-import net.sf.jsqlparser.expression.Parenthesis;
-import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
-import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
-import net.sf.jsqlparser.expression.operators.relational.InExpression;
-import net.sf.jsqlparser.schema.Column;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import java.util.Arrays;
-import java.util.Set;
-
-import static com.iailab.framework.common.util.collection.SetUtils.asSet;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link DataPermissionRuleHandler} 的单元测试
- * 主要复用了 MyBatis Plus 的 TenantLineInnerInterceptorTest 的单元测试
- * 不过它的单元测试不是很规范,考虑到是复用的,所以暂时不进行修改~
- *
- * @author iailab
- */
-public class DataPermissionRuleHandlerTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private DataPermissionRuleHandler handler;
-
-    @Mock
-    private DataPermissionRuleFactory ruleFactory;
-
-    private DataPermissionInterceptor interceptor;
-
-    @BeforeEach
-    public void setUp() {
-        interceptor = new DataPermissionInterceptor(handler);
-
-        // 租户的数据权限规则
-        DataPermissionRule tenantRule = new DataPermissionRule() {
-
-            private static final String COLUMN = "tenant_id";
-
-            @Override
-            public Set<String> getTableNames() {
-                return asSet("entity", "entity1", "entity2", "entity3", "t1", "t2", "sys_dict_item", // 支持 MyBatis Plus 的单元测试
-                        "t_user", "t_role"); // 满足自己的单元测试
-            }
-
-            @Override
-            public Expression getExpression(String tableName, Alias tableAlias) {
-                Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN);
-                LongValue value = new LongValue(1L);
-                return new EqualsTo(column, value);
-            }
-
-        };
-        // 部门的数据权限规则
-        DataPermissionRule deptRule = new DataPermissionRule() {
-
-            private static final String COLUMN = "dept_id";
-
-            @Override
-            public Set<String> getTableNames() {
-                return asSet("t_user");  // 满足自己的单元测试
-            }
-
-            @Override
-            public Expression getExpression(String tableName, Alias tableAlias) {
-                Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN);
-                ExpressionList<LongValue> values = new ExpressionList<>(new LongValue(10L),
-                        new LongValue(20L));
-                return new InExpression(column, new Parenthesis((values)));
-            }
-
-        };
-        // 设置到上下文
-        when(ruleFactory.getDataPermissionRule(any())).thenReturn(Arrays.asList(tenantRule, deptRule));
-    }
-
-    @Test
-    void delete() {
-        assertSql("delete from entity where id = ?",
-                "DELETE FROM entity WHERE id = ? AND entity.tenant_id = 1");
-    }
-
-    @Test
-    void update() {
-        assertSql("update entity set name = ? where id = ?",
-                "UPDATE entity SET name = ? WHERE id = ? AND entity.tenant_id = 1");
-    }
-
-    @Test
-    void selectSingle() {
-        // 单表
-        assertSql("select * from entity where id = ?",
-                "SELECT * FROM entity WHERE id = ? AND entity.tenant_id = 1");
-
-        assertSql("select * from entity where id = ? or name = ?",
-                "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)",
-                "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
-
-        /* not */
-        assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)",
-                "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND entity.tenant_id = 1");
-    }
-
-    @Test
-    void selectSubSelectIn() {
-        /* in */
-        assertSql("SELECT * FROM entity e WHERE e.id IN (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE e.id IN (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-        // 在最前
-        assertSql("SELECT * FROM entity e WHERE e.id IN " +
-                        "(select e1.id from entity1 e1 where e1.id = ?) and e.id = ?",
-                "SELECT * FROM entity e WHERE e.id IN " +
-                        "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ? AND e.tenant_id = 1");
-        // 在最后
-        assertSql("SELECT * FROM entity e WHERE e.id = ? and e.id IN " +
-                        "(select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE e.id = ? AND e.id IN " +
-                        "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-        // 在中间
-        assertSql("SELECT * FROM entity e WHERE e.id = ? and e.id IN " +
-                        "(select e1.id from entity1 e1 where e1.id = ?) and e.id = ?",
-                "SELECT * FROM entity e WHERE e.id = ? AND e.id IN " +
-                        "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ? AND e.tenant_id = 1");
-    }
-
-    @Test
-    void selectSubSelectEq() {
-        /* = */
-        assertSql("SELECT * FROM entity e WHERE e.id = (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-    }
-
-    @Test
-    void selectSubSelectInnerNotEq() {
-        /* inner not = */
-        assertSql("SELECT * FROM entity e WHERE not (e.id = (select e1.id from entity1 e1 where e1.id = ?))",
-                "SELECT * FROM entity e WHERE NOT (e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1)) AND e.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e WHERE not (e.id = (select e1.id from entity1 e1 where e1.id = ?) and e.id = ?)",
-                "SELECT * FROM entity e WHERE NOT (e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ?) AND e.tenant_id = 1");
-    }
-
-    @Test
-    void selectSubSelectExists() {
-        /* EXISTS */
-        assertSql("SELECT * FROM entity e WHERE EXISTS (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE EXISTS (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-
-
-        /* NOT EXISTS */
-        assertSql("SELECT * FROM entity e WHERE NOT EXISTS (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE NOT EXISTS (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-    }
-
-    @Test
-    void selectSubSelect() {
-        /* >= */
-        assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-
-
-        /* <= */
-        assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-
-
-        /* <> */
-        assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)",
-                "SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
-    }
-
-    @Test
-    void selectFromSelect() {
-        assertSql("SELECT * FROM (select e.id from entity e WHERE e.id = (select e1.id from entity1 e1 where e1.id = ?))",
-                "SELECT * FROM (SELECT e.id FROM entity e WHERE e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1)");
-    }
-
-    @Test
-    void selectBodySubSelect() {
-        assertSql("select t1.col1,(select t2.col2 from t2 t2 where t1.col1=t2.col1) from t1 t1",
-                "SELECT t1.col1, (SELECT t2.col2 FROM t2 t2 WHERE t1.col1 = t2.col1 AND t2.tenant_id = 1) FROM t1 t1 WHERE t1.tenant_id = 1");
-    }
-
-    @Test
-    void selectLeftJoin() {
-        // left join
-        assertSql("SELECT * FROM entity e " +
-                        "left join entity1 e1 on e1.id = e.id " +
-                        "WHERE e.id = ? OR e.name = ?",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "left join entity1 e1 on e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.name = ?)",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "left join entity1 e1 on e1.id = e.id " +
-                        "left join entity2 e2 on e1.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
-                        "WHERE e.tenant_id = 1");
-    }
-
-    @Test
-    void selectRightJoin() {
-        // right join
-        assertSql("SELECT * FROM entity e " +
-                        "right join entity1 e1 on e1.id = e.id",
-                "SELECT * FROM entity e " +
-                        "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
-                        "WHERE e1.tenant_id = 1");
-
-        assertSql("SELECT * FROM with_as_1 e " +
-                        "right join entity1 e1 on e1.id = e.id",
-                "SELECT * FROM with_as_1 e " +
-                        "RIGHT JOIN entity1 e1 ON e1.id = e.id " +
-                        "WHERE e1.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "right join entity1 e1 on e1.id = e.id " +
-                        "WHERE e.id = ? OR e.name = ?",
-                "SELECT * FROM entity e " +
-                        "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "right join entity1 e1 on e1.id = e.id " +
-                        "right join entity2 e2 on e1.id = e2.id ",
-                "SELECT * FROM entity e " +
-                        "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
-                        "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
-                        "WHERE e2.tenant_id = 1");
-    }
-
-    @Test
-    void selectMixJoin() {
-        assertSql("SELECT * FROM entity e " +
-                        "right join entity1 e1 on e1.id = e.id " +
-                        "left join entity2 e2 on e1.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
-                        "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
-                        "WHERE e1.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "left join entity1 e1 on e1.id = e.id " +
-                        "right join entity2 e2 on e1.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 " +
-                        "WHERE e2.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "left join entity1 e1 on e1.id = e.id " +
-                        "inner join entity2 e2 on e1.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "INNER JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 AND e2.tenant_id = 1");
-    }
-
-
-    @Test
-    void selectJoinSubSelect() {
-        assertSql("select * from (select * from entity) e1 " +
-                        "left join entity2 e2 on e1.id = e2.id",
-                "SELECT * FROM (SELECT * FROM entity WHERE entity.tenant_id = 1) e1 " +
-                        "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1");
-
-        assertSql("select * from entity1 e1 " +
-                        "left join (select * from entity2) e2 " +
-                        "on e1.id = e2.id",
-                "SELECT * FROM entity1 e1 " +
-                        "LEFT JOIN (SELECT * FROM entity2 WHERE entity2.tenant_id = 1) e2 " +
-                        "ON e1.id = e2.id " +
-                        "WHERE e1.tenant_id = 1");
-    }
-
-    @Test
-    void selectSubJoin() {
-
-        assertSql("select * FROM " +
-                        "(entity1 e1 right JOIN entity2 e2 ON e1.id = e2.id)",
-                "SELECT * FROM " +
-                        "(entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
-                        "WHERE e2.tenant_id = 1");
-
-        assertSql("select * FROM " +
-                        "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id)",
-                "SELECT * FROM " +
-                        "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
-                        "WHERE e1.tenant_id = 1");
-
-
-        assertSql("select * FROM " +
-                        "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id) " +
-                        "right join entity3 e3 on e1.id = e3.id",
-                "SELECT * FROM " +
-                        "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
-                        "RIGHT JOIN entity3 e3 ON e1.id = e3.id AND e1.tenant_id = 1 " +
-                        "WHERE e3.tenant_id = 1");
-
-
-        assertSql("select * FROM entity e " +
-                        "LEFT JOIN (entity1 e1 right join entity2 e2 ON e1.id = e2.id) " +
-                        "on e.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN (entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
-                        "ON e.id = e2.id AND e2.tenant_id = 1 " +
-                        "WHERE e.tenant_id = 1");
-
-        assertSql("select * FROM entity e " +
-                        "LEFT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
-                        "on e.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
-                        "ON e.id = e2.id AND e1.tenant_id = 1 " +
-                        "WHERE e.tenant_id = 1");
-
-        assertSql("select * FROM entity e " +
-                        "RIGHT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
-                        "on e.id = e2.id",
-                "SELECT * FROM entity e " +
-                        "RIGHT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
-                        "ON e.id = e2.id AND e.tenant_id = 1 " +
-                        "WHERE e1.tenant_id = 1");
-    }
-
-
-    @Test
-    void selectLeftJoinMultipleTrailingOn() {
-        // 多个 on 尾缀的
-        assertSql("SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 " +
-                        "LEFT JOIN entity2 e2 ON e2.id = e1.id " +
-                        "ON e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.NAME = ?)",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 " +
-                        "LEFT JOIN entity2 e2 ON e2.id = e1.id AND e2.tenant_id = 1 " +
-                        "ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.NAME = ?) AND e.tenant_id = 1");
-
-        assertSql("SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 " +
-                        "LEFT JOIN with_as_A e2 ON e2.id = e1.id " +
-                        "ON e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.NAME = ?)",
-                "SELECT * FROM entity e " +
-                        "LEFT JOIN entity1 e1 " +
-                        "LEFT JOIN with_as_A e2 ON e2.id = e1.id " +
-                        "ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.NAME = ?) AND e.tenant_id = 1");
-    }
-
-    @Test
-    void selectInnerJoin() {
-        // inner join
-        assertSql("SELECT * FROM entity e " +
-                        "inner join entity1 e1 on e1.id = e.id " +
-                        "WHERE e.id = ? OR e.name = ?",
-                "SELECT * FROM entity e " +
-                        "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
-                        "WHERE e.id = ? OR e.name = ?");
-
-        assertSql("SELECT * FROM entity e " +
-                        "inner join entity1 e1 on e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.name = ?)",
-                "SELECT * FROM entity e " +
-                        "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?)");
-
-        // 隐式内连接
-        assertSql("SELECT * FROM entity,entity1 " +
-                        "WHERE entity.id = entity1.id",
-                "SELECT * FROM entity, entity1 " +
-                        "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
-
-        // 隐式内连接
-        assertSql("SELECT * FROM entity a, with_as_entity1 b " +
-                        "WHERE a.id = b.id",
-                "SELECT * FROM entity a, with_as_entity1 b " +
-                        "WHERE a.id = b.id AND a.tenant_id = 1");
-
-        assertSql("SELECT * FROM with_as_entity a, with_as_entity1 b " +
-                        "WHERE a.id = b.id",
-                "SELECT * FROM with_as_entity a, with_as_entity1 b " +
-                        "WHERE a.id = b.id");
-
-        // SubJoin with 隐式内连接
-        assertSql("SELECT * FROM (entity,entity1) " +
-                        "WHERE entity.id = entity1.id",
-                "SELECT * FROM (entity, entity1) " +
-                        "WHERE entity.id = entity1.id " +
-                        "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
-
-        assertSql("SELECT * FROM ((entity,entity1),entity2) " +
-                        "WHERE entity.id = entity1.id and entity.id = entity2.id",
-                "SELECT * FROM ((entity, entity1), entity2) " +
-                        "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
-                        "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
-
-        assertSql("SELECT * FROM (entity,(entity1,entity2)) " +
-                        "WHERE entity.id = entity1.id and entity.id = entity2.id",
-                "SELECT * FROM (entity, (entity1, entity2)) " +
-                        "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
-                        "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
-
-        // 沙雕的括号写法
-        assertSql("SELECT * FROM (((entity,entity1))) " +
-                        "WHERE entity.id = entity1.id",
-                "SELECT * FROM (((entity, entity1))) " +
-                        "WHERE entity.id = entity1.id " +
-                        "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
-
-    }
-
-
-    @Test
-    void selectWithAs() {
-        assertSql("with with_as_A as (select * from entity) select * from with_as_A",
-                "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A");
-    }
-
-
-    @Test
-    void selectIgnoreTable() {
-        assertSql(" SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)",
-                "SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id AND item.tenant_id = 1 WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)");
-    }
-
-    private void assertSql(String sql, String targetSql) {
-        assertEquals(targetSql, interceptor.parserSingle(sql, null));
-    }
-
-    // ========== 额外的测试 ==========
-
-    @Test
-    public void testSelectSingle() {
-        // 单表
-        assertSql("select * from t_user where id = ?",
-                "SELECT * FROM t_user WHERE id = ? AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
-
-        assertSql("select * from t_user where id = ? or name = ?",
-                "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
-
-        assertSql("SELECT * FROM t_user WHERE (id = ? OR name = ?)",
-                "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
-
-        /* not */
-        assertSql("SELECT * FROM t_user WHERE not (id = ? OR name = ?)",
-                "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
-    }
-
-    @Test
-    public void testSelectLeftJoin() {
-        // left join
-        assertSql("SELECT * FROM t_user e " +
-                        "left join t_role e1 on e1.id = e.id " +
-                        "WHERE e.id = ? OR e.name = ?",
-                "SELECT * FROM t_user e " +
-                        "LEFT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");
-
-        // 条件 e.id = ? OR e.name = ? 带括号
-        assertSql("SELECT * FROM t_user e " +
-                        "left join t_role e1 on e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.name = ?)",
-                "SELECT * FROM t_user e " +
-                        "LEFT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");
-    }
-
-    @Test
-    public void testSelectRightJoin() {
-        // right join
-        assertSql("SELECT * FROM t_user e " +
-                        "right join t_role e1 on e1.id = e.id " +
-                        "WHERE e.id = ? OR e.name = ?",
-                "SELECT * FROM t_user e " +
-                        "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
-
-        // 条件 e.id = ? OR e.name = ? 带括号
-        assertSql("SELECT * FROM t_user e " +
-                        "right join t_role e1 on e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.name = ?)",
-                "SELECT * FROM t_user e " +
-                        "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " +
-                        "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
-    }
-
-    @Test
-    public void testSelectInnerJoin() {
-        // inner join
-        assertSql("SELECT * FROM t_user e " +
-                        "inner join entity1 e1 on e1.id = e.id " +
-                        "WHERE e.id = ? OR e.name = ?",
-                "SELECT * FROM t_user e " +
-                        "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " +
-                        "WHERE e.id = ? OR e.name = ?");
-
-        // 条件 e.id = ? OR e.name = ? 带括号
-        assertSql("SELECT * FROM t_user e " +
-                        "inner join entity1 e1 on e1.id = e.id " +
-                        "WHERE (e.id = ? OR e.name = ?)",
-                "SELECT * FROM t_user e " +
-                        "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " +
-                        "WHERE (e.id = ? OR e.name = ?)");
-
-        // 没有 On 的 inner join
-        assertSql("SELECT * FROM entity,entity1 " +
-                "WHERE entity.id = entity1.id",
-            "SELECT * FROM entity, entity1 " +
-                    "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java b/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java
deleted file mode 100644
index ec3a3be..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.iailab.framework.datapermission.core.rule;
-
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.iailab.framework.datapermission.core.aop.DataPermissionContextHolder;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import net.sf.jsqlparser.expression.Alias;
-import net.sf.jsqlparser.expression.Expression;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Spy;
-import org.springframework.core.annotation.AnnotationUtils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
-import static com.iailab.framework.test.core.util.RandomUtils.randomString;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link DataPermissionRuleFactoryImpl} 单元测试
- *
- * @author iailab
- */
-class DataPermissionRuleFactoryImplTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private DataPermissionRuleFactoryImpl dataPermissionRuleFactory;
-
-    @Spy
-    private List<DataPermissionRule> rules = Arrays.asList(new DataPermissionRule01(),
-            new DataPermissionRule02());
-
-    @BeforeEach
-    public void setUp() {
-        DataPermissionContextHolder.clear();
-    }
-
-    @Test
-    public void testGetDataPermissionRule_02() {
-        // 准备参数
-        String mappedStatementId = randomString();
-
-        // 调用
-        List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
-        // 断言
-        assertSame(rules, result);
-    }
-
-    @Test
-    public void testGetDataPermissionRule_03() {
-        // 准备参数
-        String mappedStatementId = randomString();
-        // mock 方法
-        DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass03.class, DataPermission.class));
-
-        // 调用
-        List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
-        // 断言
-        assertTrue(result.isEmpty());
-    }
-
-    @Test
-    public void testGetDataPermissionRule_04() {
-        // 准备参数
-        String mappedStatementId = randomString();
-        // mock 方法
-        DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass04.class, DataPermission.class));
-
-        // 调用
-        List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(DataPermissionRule01.class, result.get(0).getClass());
-    }
-
-    @Test
-    public void testGetDataPermissionRule_05() {
-        // 准备参数
-        String mappedStatementId = randomString();
-        // mock 方法
-        DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass05.class, DataPermission.class));
-
-        // 调用
-        List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
-        // 断言
-        assertEquals(1, result.size());
-        assertEquals(DataPermissionRule02.class, result.get(0).getClass());
-    }
-
-    @Test
-    public void testGetDataPermissionRule_06() {
-        // 准备参数
-        String mappedStatementId = randomString();
-        // mock 方法
-        DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass06.class, DataPermission.class));
-
-        // 调用
-        List<DataPermissionRule> result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId);
-        // 断言
-        assertSame(rules, result);
-    }
-
-    @DataPermission(enable = false)
-    static class TestClass03 {}
-
-    @DataPermission(includeRules = DataPermissionRule01.class)
-    static class TestClass04 {}
-
-    @DataPermission(excludeRules = DataPermissionRule01.class)
-    static class TestClass05 {}
-
-    @DataPermission
-    static class TestClass06 {}
-
-    static class DataPermissionRule01 implements DataPermissionRule {
-
-        @Override
-        public Set<String> getTableNames() {
-            return null;
-        }
-
-        @Override
-        public Expression getExpression(String tableName, Alias tableAlias) {
-            return null;
-        }
-
-    }
-
-    static class DataPermissionRule02 implements DataPermissionRule {
-
-        @Override
-        public Set<String> getTableNames() {
-            return null;
-        }
-
-        @Override
-        public Expression getExpression(String tableName, Alias tableAlias) {
-            return null;
-        }
-
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java b/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java
deleted file mode 100644
index 86b6587..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java
+++ /dev/null
@@ -1,239 +0,0 @@
-package com.iailab.framework.datapermission.core.rule.dept;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.util.collection.SetUtils;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.api.permission.PermissionApi;
-import com.iailab.module.system.api.permission.dto.DeptDataPermissionRespDTO;
-import net.sf.jsqlparser.expression.Alias;
-import net.sf.jsqlparser.expression.Expression;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockedStatic;
-
-import java.util.Map;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-import static com.iailab.framework.datapermission.core.rule.dept.DeptDataPermissionRule.EXPRESSION_NULL;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static com.iailab.framework.test.core.util.RandomUtils.randomString;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.same;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link DeptDataPermissionRule} 的单元测试
- *
- * @author iailab
- */
-class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
-
-    @InjectMocks
-    private DeptDataPermissionRule rule;
-
-    @Mock
-    private PermissionApi permissionApi;
-
-    @BeforeEach
-    @SuppressWarnings("unchecked")
-    public void setUp() {
-        // 清空 rule
-        rule.getTableNames().clear();
-        ((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
-        ((Map<String, String>) ReflectUtil.getFieldValue(rule, "deptColumns")).clear();
-    }
-
-    @Test // 无 LoginUser
-    public void testGetExpression_noLoginUser() {
-        // 准备参数
-        String tableName = randomString();
-        Alias tableAlias = new Alias(randomString());
-        // mock 方法
-
-        // 调用
-        Expression expression = rule.getExpression(tableName, tableAlias);
-        // 断言
-        assertNull(expression);
-    }
-
-    @Test // 无数据权限时
-    public void testGetExpression_noDeptDataPermission() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(permissionApi 返回 null)
-            when(permissionApi.getDeptDataPermission(eq(loginUser.getId()))).thenReturn(success(null));
-
-            // 调用
-            NullPointerException exception = assertThrows(NullPointerException.class,
-                    () -> rule.getExpression(tableName, tableAlias));
-            // 断言
-            assertEquals("LoginUser(1) Table(t_user/u) 未返回数据权限", exception.getMessage());
-        }
-    }
-
-    @Test // 全部数据权限
-    public void testGetExpression_allDeptDataPermission() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法(LoginUser)
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(DeptDataPermissionRespDTO)
-            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true);
-            when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
-
-            // 调用
-            Expression expression = rule.getExpression(tableName, tableAlias);
-            // 断言
-            assertNull(expression);
-            assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
-        }
-    }
-
-    @Test // 即不能查看部门,又不能查看自己,则说明 100% 无权限
-    public void testGetExpression_noDept_noSelf() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法(LoginUser)
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(DeptDataPermissionRespDTO)
-            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO();
-            when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
-
-            // 调用
-            Expression expression = rule.getExpression(tableName, tableAlias);
-            // 断言
-            assertEquals("null = null", expression.toString());
-            assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
-        }
-    }
-
-    @Test // 拼接 Dept 和 User 的条件(字段都不符合)
-    public void testGetExpression_noDeptColumn_noSelfColumn() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法(LoginUser)
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(DeptDataPermissionRespDTO)
-            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
-                    .setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true);
-            when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
-
-            // 调用
-            Expression expression = rule.getExpression(tableName, tableAlias);
-            // 断言
-            assertSame(EXPRESSION_NULL, expression);
-            assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
-        }
-    }
-
-    @Test // 拼接 Dept 和 User 的条件(self 符合)
-    public void testGetExpression_noDeptColumn_yesSelfColumn() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法(LoginUser)
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(DeptDataPermissionRespDTO)
-            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
-                    .setSelf(true);
-            when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
-            // 添加 user 字段配置
-            rule.addUserColumn("t_user", "id");
-
-            // 调用
-            Expression expression = rule.getExpression(tableName, tableAlias);
-            // 断言
-            assertEquals("u.id = 1", expression.toString());
-            assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
-        }
-    }
-
-    @Test // 拼接 Dept 和 User 的条件(dept 符合)
-    public void testGetExpression_yesDeptColumn_noSelfColumn() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法(LoginUser)
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(DeptDataPermissionRespDTO)
-            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
-                    .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L));
-            when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
-            // 添加 dept 字段配置
-            rule.addDeptColumn("t_user", "dept_id");
-
-            // 调用
-            Expression expression = rule.getExpression(tableName, tableAlias);
-            // 断言
-            assertEquals("u.dept_id IN (10, 20)", expression.toString());
-            assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
-        }
-    }
-
-    @Test // 拼接 Dept 和 User 的条件(dept + self 符合)
-    public void testGetExpression_yesDeptColumn_yesSelfColumn() {
-        try (MockedStatic<SecurityFrameworkUtils> securityFrameworkUtilsMock
-                     = mockStatic(SecurityFrameworkUtils.class)) {
-            // 准备参数
-            String tableName = "t_user";
-            Alias tableAlias = new Alias("u");
-            // mock 方法(LoginUser)
-            LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L)
-                    .setUserType(UserTypeEnum.ADMIN.getValue()));
-            securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser);
-            // mock 方法(DeptDataPermissionRespDTO)
-            DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO()
-                    .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true);
-            when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(success(deptDataPermission));
-            // 添加 user 字段配置
-            rule.addUserColumn("t_user", "id");
-            // 添加 dept 字段配置
-            rule.addDeptColumn("t_user", "dept_id");
-
-            // 调用
-            Expression expression = rule.getExpression(tableName, tableAlias);
-            // 断言
-            assertEquals("(u.dept_id IN (10, 20) OR u.id = 1)", expression.toString());
-            assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/util/DataPermissionUtilsTest.java b/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/util/DataPermissionUtilsTest.java
deleted file mode 100644
index a020683..0000000
--- a/iailab-framework/iailab-common-biz-data-permission/src/test/java/com/iailab/framework/datapermission/core/util/DataPermissionUtilsTest.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.iailab.framework.datapermission.core.util;
-
-import com.iailab.framework.datapermission.core.aop.DataPermissionContextHolder;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-public class DataPermissionUtilsTest {
-
-    @Test
-    public void testExecuteIgnore() {
-        DataPermissionUtils.executeIgnore(() -> assertFalse(DataPermissionContextHolder.get().enable()));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-ip/pom.xml b/iailab-framework/iailab-common-biz-ip/pom.xml
deleted file mode 100644
index 9ca6b36..0000000
--- a/iailab-framework/iailab-common-biz-ip/pom.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-biz-ip</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>IP 拓展,支持如下功能:
-        1. IP 功能:查询 IP 对应的城市信息
-            基于 https://gitee.com/lionsoul/ip2region 实现
-        2. 城市功能:查询城市编码对应的城市信息
-            基于 https://github.com/modood/Administrative-divisions-of-China 实现
-    </description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- IP地址检索 -->
-        <dependency>
-            <groupId>org.lionsoul</groupId>
-            <artifactId>ip2region</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有工具类需要使用到 -->
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/Area.java b/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/Area.java
deleted file mode 100644
index fba926e..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/Area.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.framework.ip.core;
-
-import com.fasterxml.jackson.annotation.JsonManagedReference;
-import com.iailab.framework.ip.core.enums.AreaTypeEnum;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.ToString;
-
-import java.util.List;
-
-/**
- * 区域节点,包括国家、省份、城市、地区等信息
- *
- * 数据可见 resources/area.csv 文件
- *
- * @author iailab
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@ToString(exclude = {"parent"})
-public class Area {
-
-    /**
-     * 编号 - 全球,即根目录
-     */
-    public static final Integer ID_GLOBAL = 0;
-    /**
-     * 编号 - 中国
-     */
-    public static final Integer ID_CHINA = 1;
-
-    /**
-     * 编号
-     */
-    private Integer id;
-    /**
-     * 名字
-     */
-    private String name;
-    /**
-     * 类型
-     *
-     * 枚举 {@link AreaTypeEnum}
-     */
-    private Integer type;
-
-    /**
-     * 父节点
-     */
-    @JsonManagedReference
-    private Area parent;
-    /**
-     * 子节点
-     */
-    @JsonManagedReference
-    private List<Area> children;
-
-}
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/enums/AreaTypeEnum.java b/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/enums/AreaTypeEnum.java
deleted file mode 100644
index ceed9b9..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/enums/AreaTypeEnum.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.framework.ip.core.enums;
-
-import com.iailab.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * 区域类型枚举
- *
- * @author iailab
- */
-@AllArgsConstructor
-@Getter
-public enum AreaTypeEnum implements IntArrayValuable {
-
-    COUNTRY(1, "国家"),
-    PROVINCE(2, "省份"),
-    CITY(3, "城市"),
-    DISTRICT(4, "地区"), // 县、镇、区等
-    ;
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AreaTypeEnum::getType).toArray();
-
-    /**
-     * 类型
-     */
-    private final Integer type;
-    /**
-     * 名字
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-}
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/utils/AreaUtils.java b/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/utils/AreaUtils.java
deleted file mode 100644
index 93298d6..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/utils/AreaUtils.java
+++ /dev/null
@@ -1,214 +0,0 @@
-package com.iailab.framework.ip.core.utils;
-
-import cn.hutool.core.io.resource.ResourceUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.text.csv.CsvRow;
-import cn.hutool.core.text.csv.CsvUtil;
-import com.iailab.framework.common.util.object.ObjectUtils;
-import com.iailab.framework.ip.core.Area;
-import com.iailab.framework.ip.core.enums.AreaTypeEnum;
-import lombok.NonNull;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
-import static com.iailab.framework.common.util.collection.CollectionUtils.findFirst;
-
-/**
- * 区域工具类
- *
- * @author iailab
- */
-@Slf4j
-public class AreaUtils {
-
-    /**
-     * 初始化 SEARCHER
-     */
-    @SuppressWarnings("InstantiationOfUtilityClass")
-    private final static AreaUtils INSTANCE = new AreaUtils();
-
-    /**
-     * Area 内存缓存,提升访问速度
-     */
-    private static Map<Integer, Area> areas;
-
-    private AreaUtils() {
-        long now = System.currentTimeMillis();
-        areas = new HashMap<>();
-        areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0,
-                null, new ArrayList<>()));
-        // 从 csv 中加载数据
-        List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
-        rows.remove(0); // 删除 header
-        for (CsvRow row : rows) {
-            // 创建 Area 对象
-            Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
-                    null, new ArrayList<>());
-            // 添加到 areas 中
-            areas.put(area.getId(), area);
-        }
-
-        // 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
-        for (CsvRow row : rows) {
-            Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
-            Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
-            Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
-            area.setParent(parent);
-            parent.getChildren().add(area);
-        }
-        log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
-    }
-
-    /**
-     * 获得指定编号对应的区域
-     *
-     * @param id 区域编号
-     * @return 区域
-     */
-    public static Area getArea(Integer id) {
-        return areas.get(id);
-    }
-
-    /**
-     * 获得指定区域对应的编号
-     *
-     * @param pathStr 区域路径,例如说:河南省/石家庄市/新华区
-     * @return 区域
-     */
-    public static Area parseArea(String pathStr) {
-        String[] paths = pathStr.split("/");
-        Area area = null;
-        for (String path : paths) {
-            if (area == null) {
-                area = findFirst(areas.values(), item -> item.getName().equals(path));
-            } else {
-                area = findFirst(area.getChildren(), item -> item.getName().equals(path));
-            }
-        }
-        return area;
-    }
-
-    /**
-     * 获取所有节点的全路径名称如:河南省/石家庄市/新华区
-     *
-     * @param areas 地区树
-     * @return 所有节点的全路径名称
-     */
-    public static List<String> getAreaNodePathList(List<Area> areas) {
-        List<String> paths = new ArrayList<>();
-        areas.forEach(area -> getAreaNodePathList(area, "", paths));
-        return paths;
-    }
-
-    /**
-     * 构建一棵树的所有节点的全路径名称,并将其存储为 "祖先/父级/子级" 的形式
-     *
-     * @param node  父节点
-     * @param path  全路径名称
-     * @param paths 全路径名称列表,省份/城市/地区
-     */
-    private static void getAreaNodePathList(Area node, String path, List<String> paths) {
-        if (node == null) {
-            return;
-        }
-        // 构建当前节点的路径
-        String currentPath = path.isEmpty() ? node.getName() : path + "/" + node.getName();
-        paths.add(currentPath);
-        // 递归遍历子节点
-        for (Area child : node.getChildren()) {
-            getAreaNodePathList(child, currentPath, paths);
-        }
-    }
-
-    /**
-     * 格式化区域
-     *
-     * @param id 区域编号
-     * @return 格式化后的区域
-     */
-    public static String format(Integer id) {
-        return format(id, " ");
-    }
-
-    /**
-     * 格式化区域
-     *
-     * 例如说:
-     * 1. id = “静安区”时:上海 上海市 静安区
-     * 2. id = “上海市”时:上海 上海市
-     * 3. id = “上海”时:上海
-     * 4. id = “美国”时:美国
-     * 当区域在中国时,默认不显示中国
-     *
-     * @param id        区域编号
-     * @param separator 分隔符
-     * @return 格式化后的区域
-     */
-    public static String format(Integer id, String separator) {
-        // 获得区域
-        Area area = areas.get(id);
-        if (area == null) {
-            return null;
-        }
-
-        // 格式化
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < AreaTypeEnum.values().length; i++) { // 避免死循环
-            sb.insert(0, area.getName());
-            // “递归”父节点
-            area = area.getParent();
-            if (area == null
-                    || ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况
-                break;
-            }
-            sb.insert(0, separator);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * 获取指定类型的区域列表
-     *
-     * @param type 区域类型
-     * @param func 转换函数
-     * @param <T>  结果类型
-     * @return 区域列表
-     */
-    public static <T> List<T> getByType(AreaTypeEnum type, Function<Area, T> func) {
-        return convertList(areas.values(), func, area -> type.getType().equals(area.getType()));
-    }
-
-    /**
-     * 根据区域编号、上级区域类型,获取上级区域编号
-     *
-     * @param id   区域编号
-     * @param type 区域类型
-     * @return 上级区域编号
-     */
-    public static Integer getParentIdByType(Integer id, @NonNull AreaTypeEnum type) {
-        for (int i = 0; i < Byte.MAX_VALUE; i++) {
-            Area area = AreaUtils.getArea(id);
-            if (area == null) {
-                return null;
-            }
-            // 情况一:匹配到,返回它
-            if (type.getType().equals(area.getType())) {
-                return area.getId();
-            }
-            // 情况二:找到根节点,返回空
-            if (area.getParent() == null || area.getParent().getId() == null) {
-                return null;
-            }
-            // 其它:继续向上查找
-            id = area.getParent().getId();
-        }
-        return null;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/utils/IPUtils.java b/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/utils/IPUtils.java
deleted file mode 100644
index a14d515..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/core/utils/IPUtils.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.iailab.framework.ip.core.utils;
-
-import cn.hutool.core.io.resource.ResourceUtil;
-import com.iailab.framework.ip.core.Area;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import org.lionsoul.ip2region.xdb.Searcher;
-
-import java.io.IOException;
-
-/**
- * IP 工具类
- *
- * IP 数据源来自 ip2region.xdb 精简版,基于 <a href="https://gitee.com/zhijiantianya/ip2region"/> 项目
- *
- * @author wanglhup
- */
-@Slf4j
-public class IPUtils {
-
-    /**
-     * 初始化 SEARCHER
-     */
-    @SuppressWarnings("InstantiationOfUtilityClass")
-    private final static IPUtils INSTANCE = new IPUtils();
-
-    /**
-     * IP 查询器,启动加载到内存中
-     */
-    private static Searcher SEARCHER;
-
-    /**
-     * 私有化构造
-     */
-    private IPUtils() {
-        try {
-            long now = System.currentTimeMillis();
-            byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
-            SEARCHER = Searcher.newWithBuffer(bytes);
-            log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
-        } catch (IOException e) {
-            log.error("启动加载 IPUtils 失败", e);
-        }
-    }
-
-    /**
-     * 查询 IP 对应的地区编号
-     *
-     * @param ip IP 地址,格式为 127.0.0.1
-     * @return 地区id
-     */
-    @SneakyThrows
-    public static Integer getAreaId(String ip) {
-        return Integer.parseInt(SEARCHER.search(ip.trim()));
-    }
-
-    /**
-     * 查询 IP 对应的地区编号
-     *
-     * @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
-     * @return 地区编号
-     */
-    @SneakyThrows
-    public static Integer getAreaId(long ip) {
-        return Integer.parseInt(SEARCHER.search(ip));
-    }
-
-    /**
-     * 查询 IP 对应的地区
-     *
-     * @param ip IP 地址,格式为 127.0.0.1
-     * @return 地区
-     */
-    public static Area getArea(String ip) {
-        return AreaUtils.getArea(getAreaId(ip));
-    }
-
-    /**
-     * 查询 IP 对应的地区
-     *
-     * @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回
-     * @return 地区
-     */
-    public static Area getArea(long ip) {
-        return AreaUtils.getArea(getAreaId(ip));
-    }
-}
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/package-info.java b/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/package-info.java
deleted file mode 100644
index 666af73..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/java/com/iailab/framework/ip/package-info.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * IP 拓展,支持如下功能:
- *
- * 1. IP 功能:查询 IP 对应的城市信息
- *      基于 https://gitee.com/lionsoul/ip2region 实现
- * 2. 城市功能:查询城市编码对应的城市信息
- *      基于 https://github.com/modood/Administrative-divisions-of-China 实现
- *
- * @author iailab
- */
-package com.iailab.framework.ip;
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/resources/area.csv b/iailab-framework/iailab-common-biz-ip/src/main/resources/area.csv
deleted file mode 100644
index 06954ba..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/resources/area.csv
+++ /dev/null
@@ -1,3662 +0,0 @@
-id,name,type,parentId
-1,中国,1,0
-2,蒙古,1,0
-3,朝鲜,1,0
-4,韩国,1,0
-5,日本,1,0
-6,菲律宾,1,0
-7,越南,1,0
-8,老挝,1,0
-9,柬埔寨,1,0
-10,缅甸,1,0
-11,泰国,1,0
-12,马来西亚,1,0
-13,文莱,1,0
-14,新加坡,1,0
-15,印度尼西亚,1,0
-16,东帝汶,1,0
-17,尼泊尔,1,0
-18,不丹,1,0
-19,孟加拉国,1,0
-20,印度,1,0
-21,巴基斯坦,1,0
-22,斯里兰卡,1,0
-23,马尔代夫,1,0
-24,哈萨克斯坦,1,0
-25,吉尔吉斯斯坦,1,0
-26,塔吉克斯坦,1,0
-27,乌兹别克斯坦,1,0
-28,土库曼斯坦,1,0
-29,阿富汗,1,0
-30,伊拉克,1,0
-31,伊朗,1,0
-32,叙利亚,1,0
-33,约旦,1,0
-34,黎巴嫩,1,0
-35,以色列,1,0
-36,巴勒斯坦,1,0
-37,沙特阿拉伯,1,0
-38,巴林,1,0
-39,卡塔尔,1,0
-40,科威特,1,0
-41,阿拉伯联合酋长国,1,0
-42,阿曼,1,0
-43,也门,1,0
-44,格鲁吉亚,1,0
-45,亚美尼亚,1,0
-46,阿塞拜疆,1,0
-47,土耳其,1,0
-48,塞浦路斯,1,0
-49,芬兰,1,0
-50,瑞典,1,0
-51,挪威,1,0
-52,冰岛,1,0
-53,丹麦,1,0
-54,爱沙尼亚,1,0
-55,拉脱维亚,1,0
-56,立陶宛,1,0
-57,白俄罗斯,1,0
-58,俄罗斯,1,0
-59,乌克兰,1,0
-60,摩尔多瓦,1,0
-61,波兰,1,0
-62,捷克,1,0
-63,斯洛伐克,1,0
-64,匈牙利,1,0
-65,德国,1,0
-66,奥地利,1,0
-67,瑞士,1,0
-68,列支敦士登,1,0
-69,英国,1,0
-70,爱尔兰,1,0
-71,荷兰,1,0
-72,比利时,1,0
-73,卢森堡,1,0
-74,法国,1,0
-75,摩纳哥,1,0
-76,罗马尼亚,1,0
-77,保加利亚,1,0
-78,塞尔维亚,1,0
-79,马其顿,1,0
-80,阿尔巴尼亚,1,0
-81,希腊,1,0
-82,斯洛文尼亚,1,0
-83,克罗地亚,1,0
-84,波斯尼亚和墨塞哥维那,1,0
-85,意大利,1,0
-86,梵蒂冈,1,0
-87,圣马力诺,1,0
-88,马耳他,1,0
-89,西班牙,1,0
-90,葡萄牙,1,0
-91,安道尔共和国,1,0
-92,埃及,1,0
-93,利比亚,1,0
-94,苏丹,1,0
-95,突尼斯,1,0
-96,阿尔及利亚,1,0
-97,摩洛哥,1,0
-98,亚速尔群岛,1,0
-99,马德拉群岛,1,0
-100,埃塞俄比亚,1,0
-101,厄立特里亚,1,0
-102,索马里,1,0
-103,吉布提,1,0
-104,肯尼亚,1,0
-105,坦桑尼亚,1,0
-106,乌干达,1,0
-107,卢旺达,1,0
-108,布隆迪,1,0
-109,塞舌尔,1,0
-110,圣多美及普林西比,1,0
-111,塞内加尔,1,0
-112,冈比亚,1,0
-113,马里,1,0
-114,布基纳法索,1,0
-115,几内亚,1,0
-116,几内亚比绍,1,0
-117,佛得角,1,0
-118,塞拉利昂,1,0
-119,利比里亚,1,0
-120,科特迪瓦,1,0
-121,加纳,1,0
-122,多哥,1,0
-123,贝宁,1,0
-124,尼日尔,1,0
-125,加那利群岛,1,0
-126,赞比亚,1,0
-127,安哥拉,1,0
-128,津巴布韦,1,0
-129,马拉维,1,0
-130,莫桑比克,1,0
-131,博茨瓦纳,1,0
-132,纳米比亚,1,0
-133,南非,1,0
-134,斯威士兰,1,0
-135,莱索托,1,0
-136,马达加斯加,1,0
-137,科摩罗,1,0
-138,毛里求斯,1,0
-139,留尼旺,1,0
-140,圣赫勒拿,1,0
-141,澳大利亚,1,0
-142,新西兰,1,0
-143,巴布亚新几内亚,1,0
-144,所罗门群岛,1,0
-145,瓦努阿图共和国,1,0
-146,密克罗尼西亚,1,0
-147,马绍尔群岛,1,0
-148,帕劳,1,0
-149,瑙鲁,1,0
-150,基里巴斯,1,0
-151,图瓦卢,1,0
-152,萨摩亚,1,0
-153,斐济,1,0
-154,汤加,1,0
-155,库克群岛,1,0
-156,关岛,1,0
-157,新喀里多尼亚,1,0
-158,法属波利尼西亚,1,0
-159,皮特凯恩岛,1,0
-160,瓦利斯与富图纳,1,0
-161,纽埃,1,0
-162,托克劳,1,0
-163,美属萨摩亚,1,0
-164,北马里亚纳,1,0
-165,加拿大,1,0
-166,美国,1,0
-167,墨西哥,1,0
-168,格陵兰,1,0
-169,危地马拉,1,0
-170,伯利兹,1,0
-171,萨尔瓦多,1,0
-172,洪都拉斯,1,0
-173,尼加拉瓜,1,0
-174,哥斯达黎加,1,0
-175,巴拿马,1,0
-176,巴哈马,1,0
-177,古巴,1,0
-178,牙买加,1,0
-179,海地,1,0
-180,多米尼加共和国,1,0
-181,安提瓜和巴布达,1,0
-182,圣基茨和尼维斯,1,0
-183,多米尼克,1,0
-184,圣卢西亚,1,0
-185,圣文森特和格林纳丁斯,1,0
-186,格林纳达,1,0
-187,巴巴多斯,1,0
-188,特立尼达和多巴哥,1,0
-189,波多黎各,1,0
-190,英属维尔京群岛,1,0
-191,美属维尔京群岛,1,0
-192,安圭拉,1,0
-193,蒙特塞拉特岛,1,0
-194,瓜德罗普,1,0
-195,马提尼克,1,0
-196,荷属安的列斯,1,0
-197,阿鲁巴,1,0
-198,特克斯和凯科斯群岛,1,0
-199,开曼群岛,1,0
-200,百慕大,1,0
-201,哥伦比亚,1,0
-202,委内瑞拉,1,0
-203,圭亚那,1,0
-204,法属圭亚那,1,0
-205,苏里南,1,0
-206,厄瓜多尔,1,0
-207,秘鲁,1,0
-208,玻利维亚,1,0
-209,巴西,1,0
-210,智利,1,0
-211,阿根廷,1,0
-212,乌拉圭,1,0
-213,巴拉圭,1,0
-214,波黑,1,0
-215,直布罗陀,1,0
-216,新喀里多尼亚群岛,1,0
-217,瓦利斯和富图纳群岛,1,0
-218,泽西岛,1,0
-219,黑山,1,0
-220,英属马恩岛,1,0
-221,尼日利亚,1,0
-222,喀麦隆,1,0
-223,加蓬,1,0
-224,乍得,1,0
-225,刚果共和国,1,0
-226,中非共和国,1,0
-227,南苏丹,1,0
-228,赤道几内亚,1,0
-229,毛里塔尼亚,1,0
-230,刚果民主共和国,1,0
-231,留尼汪岛,1,0
-232,格陵兰岛,1,0
-233,法罗群岛,1,0
-234,根西岛,1,0
-235,百慕大群岛,1,0
-236,圣皮埃尔和密克隆群岛,1,0
-237,法属圣马丁,1,0
-238,奥兰群岛,1,0
-239,北马里亚纳群岛,1,0
-240,库拉索,1,0
-241,博内尔岛,1,0
-242,圣马丁岛,1,0
-243,圣巴泰勒米岛,1,0
-244,福克兰群岛,1,0
-245,圣多美和普林西比,1,0
-246,英属印度洋领地,1,0
-247,东萨摩亚,1,0
-248,诺福克岛,1,0
-110000,北京,2,1
-120000,天津,2,1
-130000,河北省,2,1
-140000,山西省,2,1
-150000,内蒙古自治区,2,1
-210000,辽宁省,2,1
-220000,吉林省,2,1
-230000,黑龙江省,2,1
-310000,上海,2,1
-320000,江苏省,2,1
-330000,浙江省,2,1
-340000,安徽省,2,1
-350000,福建省,2,1
-360000,江西省,2,1
-370000,山东省,2,1
-410000,河南省,2,1
-420000,湖北省,2,1
-430000,湖南省,2,1
-440000,广东省,2,1
-450000,广西壮族自治区,2,1
-460000,海南省,2,1
-500000,重庆,2,1
-510000,四川省,2,1
-520000,贵州省,2,1
-530000,云南省,2,1
-540000,西藏自治区,2,1
-610000,陕西省,2,1
-620000,甘肃省,2,1
-630000,青海省,2,1
-640000,宁夏回族自治区,2,1
-650000,新疆维吾尔自治区,2,1
-110100,北京市,3,110000
-120100,天津市,3,120000
-130100,石家庄市,3,130000
-130200,唐山市,3,130000
-130300,秦皇岛市,3,130000
-130400,邯郸市,3,130000
-130500,邢台市,3,130000
-130600,保定市,3,130000
-130700,张家口市,3,130000
-130800,承德市,3,130000
-130900,沧州市,3,130000
-131000,廊坊市,3,130000
-131100,衡水市,3,130000
-140100,太原市,3,140000
-140200,大同市,3,140000
-140300,阳泉市,3,140000
-140400,长治市,3,140000
-140500,晋城市,3,140000
-140600,朔州市,3,140000
-140700,晋中市,3,140000
-140800,运城市,3,140000
-140900,忻州市,3,140000
-141000,临汾市,3,140000
-141100,吕梁市,3,140000
-150100,呼和浩特市,3,150000
-150200,包头市,3,150000
-150300,乌海市,3,150000
-150400,赤峰市,3,150000
-150500,通辽市,3,150000
-150600,鄂尔多斯市,3,150000
-150700,呼伦贝尔市,3,150000
-150800,巴彦淖尔市,3,150000
-150900,乌兰察布市,3,150000
-152200,兴安盟,3,150000
-152500,锡林郭勒盟,3,150000
-152900,阿拉善盟,3,150000
-210100,沈阳市,3,210000
-210200,大连市,3,210000
-210300,鞍山市,3,210000
-210400,抚顺市,3,210000
-210500,本溪市,3,210000
-210600,丹东市,3,210000
-210700,锦州市,3,210000
-210800,营口市,3,210000
-210900,阜新市,3,210000
-211000,辽阳市,3,210000
-211100,盘锦市,3,210000
-211200,铁岭市,3,210000
-211300,朝阳市,3,210000
-211400,葫芦岛市,3,210000
-220100,长春市,3,220000
-220200,吉林市,3,220000
-220300,四平市,3,220000
-220400,辽源市,3,220000
-220500,通化市,3,220000
-220600,白山市,3,220000
-220700,松原市,3,220000
-220800,白城市,3,220000
-222400,延边朝鲜族自治州,3,220000
-230100,哈尔滨市,3,230000
-230200,齐齐哈尔市,3,230000
-230300,鸡西市,3,230000
-230400,鹤岗市,3,230000
-230500,双鸭山市,3,230000
-230600,大庆市,3,230000
-230700,伊春市,3,230000
-230800,佳木斯市,3,230000
-230900,七台河市,3,230000
-231000,牡丹江市,3,230000
-231100,黑河市,3,230000
-231200,绥化市,3,230000
-232700,大兴安岭地区,3,230000
-310100,上海市,3,310000
-320100,南京市,3,320000
-320200,无锡市,3,320000
-320300,徐州市,3,320000
-320400,常州市,3,320000
-320500,苏州市,3,320000
-320600,南通市,3,320000
-320700,连云港市,3,320000
-320800,淮安市,3,320000
-320900,盐城市,3,320000
-321000,扬州市,3,320000
-321100,镇江市,3,320000
-321200,泰州市,3,320000
-321300,宿迁市,3,320000
-330100,杭州市,3,330000
-330200,宁波市,3,330000
-330300,温州市,3,330000
-330400,嘉兴市,3,330000
-330500,湖州市,3,330000
-330600,绍兴市,3,330000
-330700,金华市,3,330000
-330800,衢州市,3,330000
-330900,舟山市,3,330000
-331000,台州市,3,330000
-331100,丽水市,3,330000
-340100,合肥市,3,340000
-340200,芜湖市,3,340000
-340300,蚌埠市,3,340000
-340400,淮南市,3,340000
-340500,马鞍山市,3,340000
-340600,淮北市,3,340000
-340700,铜陵市,3,340000
-340800,安庆市,3,340000
-341000,黄山市,3,340000
-341100,滁州市,3,340000
-341200,阜阳市,3,340000
-341300,宿州市,3,340000
-341500,六安市,3,340000
-341600,亳州市,3,340000
-341700,池州市,3,340000
-341800,宣城市,3,340000
-350100,福州市,3,350000
-350200,厦门市,3,350000
-350300,莆田市,3,350000
-350400,三明市,3,350000
-350500,泉州市,3,350000
-350600,漳州市,3,350000
-350700,南平市,3,350000
-350800,龙岩市,3,350000
-350900,宁德市,3,350000
-360100,南昌市,3,360000
-360200,景德镇市,3,360000
-360300,萍乡市,3,360000
-360400,九江市,3,360000
-360500,新余市,3,360000
-360600,鹰潭市,3,360000
-360700,赣州市,3,360000
-360800,吉安市,3,360000
-360900,宜春市,3,360000
-361000,抚州市,3,360000
-361100,上饶市,3,360000
-370100,济南市,3,370000
-370200,青岛市,3,370000
-370300,淄博市,3,370000
-370400,枣庄市,3,370000
-370500,东营市,3,370000
-370600,烟台市,3,370000
-370700,潍坊市,3,370000
-370800,济宁市,3,370000
-370900,泰安市,3,370000
-371000,威海市,3,370000
-371100,日照市,3,370000
-371300,临沂市,3,370000
-371400,德州市,3,370000
-371500,聊城市,3,370000
-371600,滨州市,3,370000
-371700,菏泽市,3,370000
-410100,郑州市,3,410000
-410200,开封市,3,410000
-410300,洛阳市,3,410000
-410400,平顶山市,3,410000
-410500,安阳市,3,410000
-410600,鹤壁市,3,410000
-410700,新乡市,3,410000
-410800,焦作市,3,410000
-410900,濮阳市,3,410000
-411000,许昌市,3,410000
-411100,漯河市,3,410000
-411200,三门峡市,3,410000
-411300,南阳市,3,410000
-411400,商丘市,3,410000
-411500,信阳市,3,410000
-411600,周口市,3,410000
-411700,驻马店市,3,410000
-419000,省直辖县级行政区划,3,410000
-420100,武汉市,3,420000
-420200,黄石市,3,420000
-420300,十堰市,3,420000
-420500,宜昌市,3,420000
-420600,襄阳市,3,420000
-420700,鄂州市,3,420000
-420800,荆门市,3,420000
-420900,孝感市,3,420000
-421000,荆州市,3,420000
-421100,黄冈市,3,420000
-421200,咸宁市,3,420000
-421300,随州市,3,420000
-422800,恩施土家族苗族自治州,3,420000
-429000,省直辖县级行政区划,3,420000
-430100,长沙市,3,430000
-430200,株洲市,3,430000
-430300,湘潭市,3,430000
-430400,衡阳市,3,430000
-430500,邵阳市,3,430000
-430600,岳阳市,3,430000
-430700,常德市,3,430000
-430800,张家界市,3,430000
-430900,益阳市,3,430000
-431000,郴州市,3,430000
-431100,永州市,3,430000
-431200,怀化市,3,430000
-431300,娄底市,3,430000
-433100,湘西土家族苗族自治州,3,430000
-440100,广州市,3,440000
-440200,韶关市,3,440000
-440300,深圳市,3,440000
-440400,珠海市,3,440000
-440500,汕头市,3,440000
-440600,佛山市,3,440000
-440700,江门市,3,440000
-440800,湛江市,3,440000
-440900,茂名市,3,440000
-441200,肇庆市,3,440000
-441300,惠州市,3,440000
-441400,梅州市,3,440000
-441500,汕尾市,3,440000
-441600,河源市,3,440000
-441700,阳江市,3,440000
-441800,清远市,3,440000
-441900,东莞市,3,440000
-441901,莞城区,4,441900
-441902,南城区,4,441900
-441904,万江区,4,441900
-441905,石碣镇,4,441900
-441906,石龙镇,4,441900
-441907,茶山镇,4,441900
-441908,石排镇,4,441900
-441909,企石镇,4,441900
-441910,横沥镇,4,441900
-441911,桥头镇,4,441900
-441912,谢岗镇,4,441900
-441913,东坑镇,4,441900
-441914,常平镇,4,441900
-441915,寮步镇,4,441900
-441916,大朗镇,4,441900
-441917,麻涌镇,4,441900
-441918,中堂镇,4,441900
-441919,高埗镇,4,441900
-441920,樟木头镇,4,441900
-441921,大岭山镇,4,441900
-441922,望牛墩镇,4,441900
-441923,黄江镇,4,441900
-441924,洪梅镇,4,441900
-441925,清溪镇,4,441900
-441926,沙田镇,4,441900
-441927,道滘镇,4,441900
-441928,塘厦镇,4,441900
-441929,虎门镇,4,441900
-441930,厚街镇,4,441900
-441931,凤岗镇,4,441900
-441932,长安镇,4,441900
-442000,中山市,3,440000
-442001,石岐街道,4,442000
-442002,东区街道,4,442000
-442003,中山港街道,4,442000
-442004,西区街道,4,442000
-442005,南区街道,4,442000
-442006,五桂山街道,4,442000
-442007,民众街道,4,442000
-442008,南朗街道,4,442000
-442009,黄圃镇,4,442000
-442010,东凤镇,4,442000
-442011,古镇镇,4,442000
-442012,沙溪镇,4,442000
-442013,坦洲镇,4,442000
-442014,港口镇,4,442000
-442015,三角镇,4,442000
-442016,横栏镇,4,442000
-442017,南头镇,4,442000
-442018,阜沙镇,4,442000
-442019,三乡镇,4,442000
-442020,板芙镇,4,442000
-442021,大涌镇,4,442000
-442022,神湾镇,4,442000
-442023,小榄镇,4,442000
-445100,潮州市,3,440000
-445200,揭阳市,3,440000
-445300,云浮市,3,440000
-450100,南宁市,3,450000
-450200,柳州市,3,450000
-450300,桂林市,3,450000
-450400,梧州市,3,450000
-450500,北海市,3,450000
-450600,防城港市,3,450000
-450700,钦州市,3,450000
-450800,贵港市,3,450000
-450900,玉林市,3,450000
-451000,百色市,3,450000
-451100,贺州市,3,450000
-451200,河池市,3,450000
-451300,来宾市,3,450000
-451400,崇左市,3,450000
-460100,海口市,3,460000
-460200,三亚市,3,460000
-460300,三沙市,3,460000
-460400,儋州市,3,460000
-469000,省直辖县级行政区划,3,460000
-500100,重庆市,3,500000
-510100,成都市,3,510000
-510300,自贡市,3,510000
-510400,攀枝花市,3,510000
-510500,泸州市,3,510000
-510600,德阳市,3,510000
-510700,绵阳市,3,510000
-510800,广元市,3,510000
-510900,遂宁市,3,510000
-511000,内江市,3,510000
-511100,乐山市,3,510000
-511300,南充市,3,510000
-511400,眉山市,3,510000
-511500,宜宾市,3,510000
-511600,广安市,3,510000
-511700,达州市,3,510000
-511800,雅安市,3,510000
-511900,巴中市,3,510000
-512000,资阳市,3,510000
-513200,阿坝藏族羌族自治州,3,510000
-513300,甘孜藏族自治州,3,510000
-513400,凉山彝族自治州,3,510000
-520100,贵阳市,3,520000
-520200,六盘水市,3,520000
-520300,遵义市,3,520000
-520400,安顺市,3,520000
-520500,毕节市,3,520000
-520600,铜仁市,3,520000
-522300,黔西南布依族苗族自治州,3,520000
-522600,黔东南苗族侗族自治州,3,520000
-522700,黔南布依族苗族自治州,3,520000
-530100,昆明市,3,530000
-530300,曲靖市,3,530000
-530400,玉溪市,3,530000
-530500,保山市,3,530000
-530600,昭通市,3,530000
-530700,丽江市,3,530000
-530800,普洱市,3,530000
-530900,临沧市,3,530000
-532300,楚雄彝族自治州,3,530000
-532500,红河哈尼族彝族自治州,3,530000
-532600,文山壮族苗族自治州,3,530000
-532800,西双版纳傣族自治州,3,530000
-532900,大理白族自治州,3,530000
-533100,德宏傣族景颇族自治州,3,530000
-533300,怒江傈僳族自治州,3,530000
-533400,迪庆藏族自治州,3,530000
-540100,拉萨市,3,540000
-540200,日喀则市,3,540000
-540300,昌都市,3,540000
-540400,林芝市,3,540000
-540500,山南市,3,540000
-540600,那曲市,3,540000
-542500,阿里地区,3,540000
-610100,西安市,3,610000
-610200,铜川市,3,610000
-610300,宝鸡市,3,610000
-610400,咸阳市,3,610000
-610500,渭南市,3,610000
-610600,延安市,3,610000
-610700,汉中市,3,610000
-610800,榆林市,3,610000
-610900,安康市,3,610000
-611000,商洛市,3,610000
-620100,兰州市,3,620000
-620200,嘉峪关市,3,620000
-620300,金昌市,3,620000
-620400,白银市,3,620000
-620500,天水市,3,620000
-620600,武威市,3,620000
-620700,张掖市,3,620000
-620800,平凉市,3,620000
-620900,酒泉市,3,620000
-621000,庆阳市,3,620000
-621100,定西市,3,620000
-621200,陇南市,3,620000
-622900,临夏回族自治州,3,620000
-623000,甘南藏族自治州,3,620000
-630100,西宁市,3,630000
-630200,海东市,3,630000
-632200,海北藏族自治州,3,630000
-632300,黄南藏族自治州,3,630000
-632500,海南藏族自治州,3,630000
-632600,果洛藏族自治州,3,630000
-632700,玉树藏族自治州,3,630000
-632800,海西蒙古族藏族自治州,3,630000
-640100,银川市,3,640000
-640200,石嘴山市,3,640000
-640300,吴忠市,3,640000
-640400,固原市,3,640000
-640500,中卫市,3,640000
-650100,乌鲁木齐市,3,650000
-650200,克拉玛依市,3,650000
-650400,吐鲁番市,3,650000
-650500,哈密市,3,650000
-652300,昌吉回族自治州,3,650000
-652700,博尔塔拉蒙古自治州,3,650000
-652800,巴音郭楞蒙古自治州,3,650000
-652900,阿克苏地区,3,650000
-653000,克孜勒苏柯尔克孜自治州,3,650000
-653100,喀什地区,3,650000
-653200,和田地区,3,650000
-654000,伊犁哈萨克自治州,3,650000
-654200,塔城地区,3,650000
-654300,阿勒泰地区,3,650000
-659000,自治区直辖县级行政区划,3,650000
-110101,东城区,4,110100
-110102,西城区,4,110100
-110105,朝阳区,4,110100
-110106,丰台区,4,110100
-110107,石景山区,4,110100
-110108,海淀区,4,110100
-110109,门头沟区,4,110100
-110111,房山区,4,110100
-110112,通州区,4,110100
-110113,顺义区,4,110100
-110114,昌平区,4,110100
-110115,大兴区,4,110100
-110116,怀柔区,4,110100
-110117,平谷区,4,110100
-110118,密云区,4,110100
-110119,延庆区,4,110100
-120101,和平区,4,120100
-120102,河东区,4,120100
-120103,河西区,4,120100
-120104,南开区,4,120100
-120105,河北区,4,120100
-120106,红桥区,4,120100
-120110,东丽区,4,120100
-120111,西青区,4,120100
-120112,津南区,4,120100
-120113,北辰区,4,120100
-120114,武清区,4,120100
-120115,宝坻区,4,120100
-120116,滨海新区,4,120100
-120117,宁河区,4,120100
-120118,静海区,4,120100
-120119,蓟州区,4,120100
-130102,长安区,4,130100
-130104,桥西区,4,130100
-130105,新华区,4,130100
-130107,井陉矿区,4,130100
-130108,裕华区,4,130100
-130109,藁城区,4,130100
-130110,鹿泉区,4,130100
-130111,栾城区,4,130100
-130121,井陉县,4,130100
-130123,正定县,4,130100
-130125,行唐县,4,130100
-130126,灵寿县,4,130100
-130127,高邑县,4,130100
-130128,深泽县,4,130100
-130129,赞皇县,4,130100
-130130,无极县,4,130100
-130131,平山县,4,130100
-130132,元氏县,4,130100
-130133,赵县,4,130100
-130171,石家庄高新技术产业开发区,4,130100
-130172,石家庄循环化工园区,4,130100
-130181,辛集市,4,130100
-130183,晋州市,4,130100
-130184,新乐市,4,130100
-130202,路南区,4,130200
-130203,路北区,4,130200
-130204,古冶区,4,130200
-130205,开平区,4,130200
-130207,丰南区,4,130200
-130208,丰润区,4,130200
-130209,曹妃甸区,4,130200
-130224,滦南县,4,130200
-130225,乐亭县,4,130200
-130227,迁西县,4,130200
-130229,玉田县,4,130200
-130271,河北唐山芦台经济开发区,4,130200
-130272,唐山市汉沽管理区,4,130200
-130273,唐山高新技术产业开发区,4,130200
-130274,河北唐山海港经济开发区,4,130200
-130281,遵化市,4,130200
-130283,迁安市,4,130200
-130284,滦州市,4,130200
-130302,海港区,4,130300
-130303,山海关区,4,130300
-130304,北戴河区,4,130300
-130306,抚宁区,4,130300
-130321,青龙满族自治县,4,130300
-130322,昌黎县,4,130300
-130324,卢龙县,4,130300
-130371,秦皇岛市经济技术开发区,4,130300
-130372,北戴河新区,4,130300
-130402,邯山区,4,130400
-130403,丛台区,4,130400
-130404,复兴区,4,130400
-130406,峰峰矿区,4,130400
-130407,肥乡区,4,130400
-130408,永年区,4,130400
-130423,临漳县,4,130400
-130424,成安县,4,130400
-130425,大名县,4,130400
-130426,涉县,4,130400
-130427,磁县,4,130400
-130430,邱县,4,130400
-130431,鸡泽县,4,130400
-130432,广平县,4,130400
-130433,馆陶县,4,130400
-130434,魏县,4,130400
-130435,曲周县,4,130400
-130471,邯郸经济技术开发区,4,130400
-130473,邯郸冀南新区,4,130400
-130481,武安市,4,130400
-130502,襄都区,4,130500
-130503,信都区,4,130500
-130505,任泽区,4,130500
-130506,南和区,4,130500
-130522,临城县,4,130500
-130523,内丘县,4,130500
-130524,柏乡县,4,130500
-130525,隆尧县,4,130500
-130528,宁晋县,4,130500
-130529,巨鹿县,4,130500
-130530,新河县,4,130500
-130531,广宗县,4,130500
-130532,平乡县,4,130500
-130533,威县,4,130500
-130534,清河县,4,130500
-130535,临西县,4,130500
-130571,河北邢台经济开发区,4,130500
-130581,南宫市,4,130500
-130582,沙河市,4,130500
-130602,竞秀区,4,130600
-130606,莲池区,4,130600
-130607,满城区,4,130600
-130608,清苑区,4,130600
-130609,徐水区,4,130600
-130623,涞水县,4,130600
-130624,阜平县,4,130600
-130626,定兴县,4,130600
-130627,唐县,4,130600
-130628,高阳县,4,130600
-130629,容城县,4,130600
-130630,涞源县,4,130600
-130631,望都县,4,130600
-130632,安新县,4,130600
-130633,易县,4,130600
-130634,曲阳县,4,130600
-130635,蠡县,4,130600
-130636,顺平县,4,130600
-130637,博野县,4,130600
-130638,雄县,4,130600
-130671,保定高新技术产业开发区,4,130600
-130672,保定白沟新城,4,130600
-130681,涿州市,4,130600
-130682,定州市,4,130600
-130683,安国市,4,130600
-130684,高碑店市,4,130600
-130702,桥东区,4,130700
-130703,桥西区,4,130700
-130705,宣化区,4,130700
-130706,下花园区,4,130700
-130708,万全区,4,130700
-130709,崇礼区,4,130700
-130722,张北县,4,130700
-130723,康保县,4,130700
-130724,沽源县,4,130700
-130725,尚义县,4,130700
-130726,蔚县,4,130700
-130727,阳原县,4,130700
-130728,怀安县,4,130700
-130730,怀来县,4,130700
-130731,涿鹿县,4,130700
-130732,赤城县,4,130700
-130771,张家口经济开发区,4,130700
-130772,张家口市察北管理区,4,130700
-130773,张家口市塞北管理区,4,130700
-130802,双桥区,4,130800
-130803,双滦区,4,130800
-130804,鹰手营子矿区,4,130800
-130821,承德县,4,130800
-130822,兴隆县,4,130800
-130824,滦平县,4,130800
-130825,隆化县,4,130800
-130826,丰宁满族自治县,4,130800
-130827,宽城满族自治县,4,130800
-130828,围场满族蒙古族自治县,4,130800
-130871,承德高新技术产业开发区,4,130800
-130881,平泉市,4,130800
-130902,新华区,4,130900
-130903,运河区,4,130900
-130921,沧县,4,130900
-130922,青县,4,130900
-130923,东光县,4,130900
-130924,海兴县,4,130900
-130925,盐山县,4,130900
-130926,肃宁县,4,130900
-130927,南皮县,4,130900
-130928,吴桥县,4,130900
-130929,献县,4,130900
-130930,孟村回族自治县,4,130900
-130971,河北沧州经济开发区,4,130900
-130972,沧州高新技术产业开发区,4,130900
-130973,沧州渤海新区,4,130900
-130981,泊头市,4,130900
-130982,任丘市,4,130900
-130983,黄骅市,4,130900
-130984,河间市,4,130900
-131002,安次区,4,131000
-131003,广阳区,4,131000
-131022,固安县,4,131000
-131023,永清县,4,131000
-131024,香河县,4,131000
-131025,大城县,4,131000
-131026,文安县,4,131000
-131028,大厂回族自治县,4,131000
-131071,廊坊经济技术开发区,4,131000
-131081,霸州市,4,131000
-131082,三河市,4,131000
-131102,桃城区,4,131100
-131103,冀州区,4,131100
-131121,枣强县,4,131100
-131122,武邑县,4,131100
-131123,武强县,4,131100
-131124,饶阳县,4,131100
-131125,安平县,4,131100
-131126,故城县,4,131100
-131127,景县,4,131100
-131128,阜城县,4,131100
-131171,河北衡水高新技术产业开发区,4,131100
-131172,衡水滨湖新区,4,131100
-131182,深州市,4,131100
-140105,小店区,4,140100
-140106,迎泽区,4,140100
-140107,杏花岭区,4,140100
-140108,尖草坪区,4,140100
-140109,万柏林区,4,140100
-140110,晋源区,4,140100
-140121,清徐县,4,140100
-140122,阳曲县,4,140100
-140123,娄烦县,4,140100
-140171,山西转型综合改革示范区,4,140100
-140181,古交市,4,140100
-140212,新荣区,4,140200
-140213,平城区,4,140200
-140214,云冈区,4,140200
-140215,云州区,4,140200
-140221,阳高县,4,140200
-140222,天镇县,4,140200
-140223,广灵县,4,140200
-140224,灵丘县,4,140200
-140225,浑源县,4,140200
-140226,左云县,4,140200
-140271,山西大同经济开发区,4,140200
-140302,城区,4,140300
-140303,矿区,4,140300
-140311,郊区,4,140300
-140321,平定县,4,140300
-140322,盂县,4,140300
-140403,潞州区,4,140400
-140404,上党区,4,140400
-140405,屯留区,4,140400
-140406,潞城区,4,140400
-140423,襄垣县,4,140400
-140425,平顺县,4,140400
-140426,黎城县,4,140400
-140427,壶关县,4,140400
-140428,长子县,4,140400
-140429,武乡县,4,140400
-140430,沁县,4,140400
-140431,沁源县,4,140400
-140471,山西长治高新技术产业园区,4,140400
-140502,城区,4,140500
-140521,沁水县,4,140500
-140522,阳城县,4,140500
-140524,陵川县,4,140500
-140525,泽州县,4,140500
-140581,高平市,4,140500
-140602,朔城区,4,140600
-140603,平鲁区,4,140600
-140621,山阴县,4,140600
-140622,应县,4,140600
-140623,右玉县,4,140600
-140671,山西朔州经济开发区,4,140600
-140681,怀仁市,4,140600
-140702,榆次区,4,140700
-140703,太谷区,4,140700
-140721,榆社县,4,140700
-140722,左权县,4,140700
-140723,和顺县,4,140700
-140724,昔阳县,4,140700
-140725,寿阳县,4,140700
-140727,祁县,4,140700
-140728,平遥县,4,140700
-140729,灵石县,4,140700
-140781,介休市,4,140700
-140802,盐湖区,4,140800
-140821,临猗县,4,140800
-140822,万荣县,4,140800
-140823,闻喜县,4,140800
-140824,稷山县,4,140800
-140825,新绛县,4,140800
-140826,绛县,4,140800
-140827,垣曲县,4,140800
-140828,夏县,4,140800
-140829,平陆县,4,140800
-140830,芮城县,4,140800
-140881,永济市,4,140800
-140882,河津市,4,140800
-140902,忻府区,4,140900
-140921,定襄县,4,140900
-140922,五台县,4,140900
-140923,代县,4,140900
-140924,繁峙县,4,140900
-140925,宁武县,4,140900
-140926,静乐县,4,140900
-140927,神池县,4,140900
-140928,五寨县,4,140900
-140929,岢岚县,4,140900
-140930,河曲县,4,140900
-140931,保德县,4,140900
-140932,偏关县,4,140900
-140971,五台山风景名胜区,4,140900
-140981,原平市,4,140900
-141002,尧都区,4,141000
-141021,曲沃县,4,141000
-141022,翼城县,4,141000
-141023,襄汾县,4,141000
-141024,洪洞县,4,141000
-141025,古县,4,141000
-141026,安泽县,4,141000
-141027,浮山县,4,141000
-141028,吉县,4,141000
-141029,乡宁县,4,141000
-141030,大宁县,4,141000
-141031,隰县,4,141000
-141032,永和县,4,141000
-141033,蒲县,4,141000
-141034,汾西县,4,141000
-141081,侯马市,4,141000
-141082,霍州市,4,141000
-141102,离石区,4,141100
-141121,文水县,4,141100
-141122,交城县,4,141100
-141123,兴县,4,141100
-141124,临县,4,141100
-141125,柳林县,4,141100
-141126,石楼县,4,141100
-141127,岚县,4,141100
-141128,方山县,4,141100
-141129,中阳县,4,141100
-141130,交口县,4,141100
-141181,孝义市,4,141100
-141182,汾阳市,4,141100
-150102,新城区,4,150100
-150103,回民区,4,150100
-150104,玉泉区,4,150100
-150105,赛罕区,4,150100
-150121,土默特左旗,4,150100
-150122,托克托县,4,150100
-150123,和林格尔县,4,150100
-150124,清水河县,4,150100
-150125,武川县,4,150100
-150172,呼和浩特经济技术开发区,4,150100
-150202,东河区,4,150200
-150203,昆都仑区,4,150200
-150204,青山区,4,150200
-150205,石拐区,4,150200
-150206,白云鄂博矿区,4,150200
-150207,九原区,4,150200
-150221,土默特右旗,4,150200
-150222,固阳县,4,150200
-150223,达尔罕茂明安联合旗,4,150200
-150271,包头稀土高新技术产业开发区,4,150200
-150302,海勃湾区,4,150300
-150303,海南区,4,150300
-150304,乌达区,4,150300
-150402,红山区,4,150400
-150403,元宝山区,4,150400
-150404,松山区,4,150400
-150421,阿鲁科尔沁旗,4,150400
-150422,巴林左旗,4,150400
-150423,巴林右旗,4,150400
-150424,林西县,4,150400
-150425,克什克腾旗,4,150400
-150426,翁牛特旗,4,150400
-150428,喀喇沁旗,4,150400
-150429,宁城县,4,150400
-150430,敖汉旗,4,150400
-150502,科尔沁区,4,150500
-150521,科尔沁左翼中旗,4,150500
-150522,科尔沁左翼后旗,4,150500
-150523,开鲁县,4,150500
-150524,库伦旗,4,150500
-150525,奈曼旗,4,150500
-150526,扎鲁特旗,4,150500
-150571,通辽经济技术开发区,4,150500
-150581,霍林郭勒市,4,150500
-150602,东胜区,4,150600
-150603,康巴什区,4,150600
-150621,达拉特旗,4,150600
-150622,准格尔旗,4,150600
-150623,鄂托克前旗,4,150600
-150624,鄂托克旗,4,150600
-150625,杭锦旗,4,150600
-150626,乌审旗,4,150600
-150627,伊金霍洛旗,4,150600
-150702,海拉尔区,4,150700
-150703,扎赉诺尔区,4,150700
-150721,阿荣旗,4,150700
-150722,莫力达瓦达斡尔族自治旗,4,150700
-150723,鄂伦春自治旗,4,150700
-150724,鄂温克族自治旗,4,150700
-150725,陈巴尔虎旗,4,150700
-150726,新巴尔虎左旗,4,150700
-150727,新巴尔虎右旗,4,150700
-150781,满洲里市,4,150700
-150782,牙克石市,4,150700
-150783,扎兰屯市,4,150700
-150784,额尔古纳市,4,150700
-150785,根河市,4,150700
-150802,临河区,4,150800
-150821,五原县,4,150800
-150822,磴口县,4,150800
-150823,乌拉特前旗,4,150800
-150824,乌拉特中旗,4,150800
-150825,乌拉特后旗,4,150800
-150826,杭锦后旗,4,150800
-150902,集宁区,4,150900
-150921,卓资县,4,150900
-150922,化德县,4,150900
-150923,商都县,4,150900
-150924,兴和县,4,150900
-150925,凉城县,4,150900
-150926,察哈尔右翼前旗,4,150900
-150927,察哈尔右翼中旗,4,150900
-150928,察哈尔右翼后旗,4,150900
-150929,四子王旗,4,150900
-150981,丰镇市,4,150900
-152201,乌兰浩特市,4,152200
-152202,阿尔山市,4,152200
-152221,科尔沁右翼前旗,4,152200
-152222,科尔沁右翼中旗,4,152200
-152223,扎赉特旗,4,152200
-152224,突泉县,4,152200
-152501,二连浩特市,4,152500
-152502,锡林浩特市,4,152500
-152522,阿巴嘎旗,4,152500
-152523,苏尼特左旗,4,152500
-152524,苏尼特右旗,4,152500
-152525,东乌珠穆沁旗,4,152500
-152526,西乌珠穆沁旗,4,152500
-152527,太仆寺旗,4,152500
-152528,镶黄旗,4,152500
-152529,正镶白旗,4,152500
-152530,正蓝旗,4,152500
-152531,多伦县,4,152500
-152571,乌拉盖管委会,4,152500
-152921,阿拉善左旗,4,152900
-152922,阿拉善右旗,4,152900
-152923,额济纳旗,4,152900
-152971,内蒙古阿拉善高新技术产业开发区,4,152900
-210102,和平区,4,210100
-210103,沈河区,4,210100
-210104,大东区,4,210100
-210105,皇姑区,4,210100
-210106,铁西区,4,210100
-210111,苏家屯区,4,210100
-210112,浑南区,4,210100
-210113,沈北新区,4,210100
-210114,于洪区,4,210100
-210115,辽中区,4,210100
-210123,康平县,4,210100
-210124,法库县,4,210100
-210181,新民市,4,210100
-210202,中山区,4,210200
-210203,西岗区,4,210200
-210204,沙河口区,4,210200
-210211,甘井子区,4,210200
-210212,旅顺口区,4,210200
-210213,金州区,4,210200
-210214,普兰店区,4,210200
-210224,长海县,4,210200
-210281,瓦房店市,4,210200
-210283,庄河市,4,210200
-210302,铁东区,4,210300
-210303,铁西区,4,210300
-210304,立山区,4,210300
-210311,千山区,4,210300
-210321,台安县,4,210300
-210323,岫岩满族自治县,4,210300
-210381,海城市,4,210300
-210402,新抚区,4,210400
-210403,东洲区,4,210400
-210404,望花区,4,210400
-210411,顺城区,4,210400
-210421,抚顺县,4,210400
-210422,新宾满族自治县,4,210400
-210423,清原满族自治县,4,210400
-210502,平山区,4,210500
-210503,溪湖区,4,210500
-210504,明山区,4,210500
-210505,南芬区,4,210500
-210521,本溪满族自治县,4,210500
-210522,桓仁满族自治县,4,210500
-210602,元宝区,4,210600
-210603,振兴区,4,210600
-210604,振安区,4,210600
-210624,宽甸满族自治县,4,210600
-210681,东港市,4,210600
-210682,凤城市,4,210600
-210702,古塔区,4,210700
-210703,凌河区,4,210700
-210711,太和区,4,210700
-210726,黑山县,4,210700
-210727,义县,4,210700
-210781,凌海市,4,210700
-210782,北镇市,4,210700
-210802,站前区,4,210800
-210803,西市区,4,210800
-210804,鲅鱼圈区,4,210800
-210811,老边区,4,210800
-210881,盖州市,4,210800
-210882,大石桥市,4,210800
-210902,海州区,4,210900
-210903,新邱区,4,210900
-210904,太平区,4,210900
-210905,清河门区,4,210900
-210911,细河区,4,210900
-210921,阜新蒙古族自治县,4,210900
-210922,彰武县,4,210900
-211002,白塔区,4,211000
-211003,文圣区,4,211000
-211004,宏伟区,4,211000
-211005,弓长岭区,4,211000
-211011,太子河区,4,211000
-211021,辽阳县,4,211000
-211081,灯塔市,4,211000
-211102,双台子区,4,211100
-211103,兴隆台区,4,211100
-211104,大洼区,4,211100
-211122,盘山县,4,211100
-211202,银州区,4,211200
-211204,清河区,4,211200
-211221,铁岭县,4,211200
-211223,西丰县,4,211200
-211224,昌图县,4,211200
-211281,调兵山市,4,211200
-211282,开原市,4,211200
-211302,双塔区,4,211300
-211303,龙城区,4,211300
-211321,朝阳县,4,211300
-211322,建平县,4,211300
-211324,喀喇沁左翼蒙古族自治县,4,211300
-211381,北票市,4,211300
-211382,凌源市,4,211300
-211402,连山区,4,211400
-211403,龙港区,4,211400
-211404,南票区,4,211400
-211421,绥中县,4,211400
-211422,建昌县,4,211400
-211481,兴城市,4,211400
-220102,南关区,4,220100
-220103,宽城区,4,220100
-220104,朝阳区,4,220100
-220105,二道区,4,220100
-220106,绿园区,4,220100
-220112,双阳区,4,220100
-220113,九台区,4,220100
-220122,农安县,4,220100
-220171,长春经济技术开发区,4,220100
-220172,长春净月高新技术产业开发区,4,220100
-220173,长春高新技术产业开发区,4,220100
-220174,长春汽车经济技术开发区,4,220100
-220182,榆树市,4,220100
-220183,德惠市,4,220100
-220184,公主岭市,4,220100
-220202,昌邑区,4,220200
-220203,龙潭区,4,220200
-220204,船营区,4,220200
-220211,丰满区,4,220200
-220221,永吉县,4,220200
-220271,吉林经济开发区,4,220200
-220272,吉林高新技术产业开发区,4,220200
-220273,吉林中国新加坡食品区,4,220200
-220281,蛟河市,4,220200
-220282,桦甸市,4,220200
-220283,舒兰市,4,220200
-220284,磐石市,4,220200
-220302,铁西区,4,220300
-220303,铁东区,4,220300
-220322,梨树县,4,220300
-220323,伊通满族自治县,4,220300
-220382,双辽市,4,220300
-220402,龙山区,4,220400
-220403,西安区,4,220400
-220421,东丰县,4,220400
-220422,东辽县,4,220400
-220502,东昌区,4,220500
-220503,二道江区,4,220500
-220521,通化县,4,220500
-220523,辉南县,4,220500
-220524,柳河县,4,220500
-220581,梅河口市,4,220500
-220582,集安市,4,220500
-220602,浑江区,4,220600
-220605,江源区,4,220600
-220621,抚松县,4,220600
-220622,靖宇县,4,220600
-220623,长白朝鲜族自治县,4,220600
-220681,临江市,4,220600
-220702,宁江区,4,220700
-220721,前郭尔罗斯蒙古族自治县,4,220700
-220722,长岭县,4,220700
-220723,乾安县,4,220700
-220771,吉林松原经济开发区,4,220700
-220781,扶余市,4,220700
-220802,洮北区,4,220800
-220821,镇赉县,4,220800
-220822,通榆县,4,220800
-220871,吉林白城经济开发区,4,220800
-220881,洮南市,4,220800
-220882,大安市,4,220800
-222401,延吉市,4,222400
-222402,图们市,4,222400
-222403,敦化市,4,222400
-222404,珲春市,4,222400
-222405,龙井市,4,222400
-222406,和龙市,4,222400
-222424,汪清县,4,222400
-222426,安图县,4,222400
-230102,道里区,4,230100
-230103,南岗区,4,230100
-230104,道外区,4,230100
-230108,平房区,4,230100
-230109,松北区,4,230100
-230110,香坊区,4,230100
-230111,呼兰区,4,230100
-230112,阿城区,4,230100
-230113,双城区,4,230100
-230123,依兰县,4,230100
-230124,方正县,4,230100
-230125,宾县,4,230100
-230126,巴彦县,4,230100
-230127,木兰县,4,230100
-230128,通河县,4,230100
-230129,延寿县,4,230100
-230183,尚志市,4,230100
-230184,五常市,4,230100
-230202,龙沙区,4,230200
-230203,建华区,4,230200
-230204,铁锋区,4,230200
-230205,昂昂溪区,4,230200
-230206,富拉尔基区,4,230200
-230207,碾子山区,4,230200
-230208,梅里斯达斡尔族区,4,230200
-230221,龙江县,4,230200
-230223,依安县,4,230200
-230224,泰来县,4,230200
-230225,甘南县,4,230200
-230227,富裕县,4,230200
-230229,克山县,4,230200
-230230,克东县,4,230200
-230231,拜泉县,4,230200
-230281,讷河市,4,230200
-230302,鸡冠区,4,230300
-230303,恒山区,4,230300
-230304,滴道区,4,230300
-230305,梨树区,4,230300
-230306,城子河区,4,230300
-230307,麻山区,4,230300
-230321,鸡东县,4,230300
-230381,虎林市,4,230300
-230382,密山市,4,230300
-230402,向阳区,4,230400
-230403,工农区,4,230400
-230404,南山区,4,230400
-230405,兴安区,4,230400
-230406,东山区,4,230400
-230407,兴山区,4,230400
-230421,萝北县,4,230400
-230422,绥滨县,4,230400
-230502,尖山区,4,230500
-230503,岭东区,4,230500
-230505,四方台区,4,230500
-230506,宝山区,4,230500
-230521,集贤县,4,230500
-230522,友谊县,4,230500
-230523,宝清县,4,230500
-230524,饶河县,4,230500
-230602,萨尔图区,4,230600
-230603,龙凤区,4,230600
-230604,让胡路区,4,230600
-230605,红岗区,4,230600
-230606,大同区,4,230600
-230621,肇州县,4,230600
-230622,肇源县,4,230600
-230623,林甸县,4,230600
-230624,杜尔伯特蒙古族自治县,4,230600
-230671,大庆高新技术产业开发区,4,230600
-230717,伊美区,4,230700
-230718,乌翠区,4,230700
-230719,友好区,4,230700
-230722,嘉荫县,4,230700
-230723,汤旺县,4,230700
-230724,丰林县,4,230700
-230725,大箐山县,4,230700
-230726,南岔县,4,230700
-230751,金林区,4,230700
-230781,铁力市,4,230700
-230803,向阳区,4,230800
-230804,前进区,4,230800
-230805,东风区,4,230800
-230811,郊区,4,230800
-230822,桦南县,4,230800
-230826,桦川县,4,230800
-230828,汤原县,4,230800
-230881,同江市,4,230800
-230882,富锦市,4,230800
-230883,抚远市,4,230800
-230902,新兴区,4,230900
-230903,桃山区,4,230900
-230904,茄子河区,4,230900
-230921,勃利县,4,230900
-231002,东安区,4,231000
-231003,阳明区,4,231000
-231004,爱民区,4,231000
-231005,西安区,4,231000
-231025,林口县,4,231000
-231071,牡丹江经济技术开发区,4,231000
-231081,绥芬河市,4,231000
-231083,海林市,4,231000
-231084,宁安市,4,231000
-231085,穆棱市,4,231000
-231086,东宁市,4,231000
-231102,爱辉区,4,231100
-231123,逊克县,4,231100
-231124,孙吴县,4,231100
-231181,北安市,4,231100
-231182,五大连池市,4,231100
-231183,嫩江市,4,231100
-231202,北林区,4,231200
-231221,望奎县,4,231200
-231222,兰西县,4,231200
-231223,青冈县,4,231200
-231224,庆安县,4,231200
-231225,明水县,4,231200
-231226,绥棱县,4,231200
-231281,安达市,4,231200
-231282,肇东市,4,231200
-231283,海伦市,4,231200
-232701,漠河市,4,232700
-232721,呼玛县,4,232700
-232722,塔河县,4,232700
-232761,加格达奇区,4,232700
-232762,松岭区,4,232700
-232763,新林区,4,232700
-232764,呼中区,4,232700
-310101,黄浦区,4,310100
-310104,徐汇区,4,310100
-310105,长宁区,4,310100
-310106,静安区,4,310100
-310107,普陀区,4,310100
-310109,虹口区,4,310100
-310110,杨浦区,4,310100
-310112,闵行区,4,310100
-310113,宝山区,4,310100
-310114,嘉定区,4,310100
-310115,浦东新区,4,310100
-310116,金山区,4,310100
-310117,松江区,4,310100
-310118,青浦区,4,310100
-310120,奉贤区,4,310100
-310151,崇明区,4,310100
-320102,玄武区,4,320100
-320104,秦淮区,4,320100
-320105,建邺区,4,320100
-320106,鼓楼区,4,320100
-320111,浦口区,4,320100
-320113,栖霞区,4,320100
-320114,雨花台区,4,320100
-320115,江宁区,4,320100
-320116,六合区,4,320100
-320117,溧水区,4,320100
-320118,高淳区,4,320100
-320205,锡山区,4,320200
-320206,惠山区,4,320200
-320211,滨湖区,4,320200
-320213,梁溪区,4,320200
-320214,新吴区,4,320200
-320281,江阴市,4,320200
-320282,宜兴市,4,320200
-320302,鼓楼区,4,320300
-320303,云龙区,4,320300
-320305,贾汪区,4,320300
-320311,泉山区,4,320300
-320312,铜山区,4,320300
-320321,丰县,4,320300
-320322,沛县,4,320300
-320324,睢宁县,4,320300
-320371,徐州经济技术开发区,4,320300
-320381,新沂市,4,320300
-320382,邳州市,4,320300
-320402,天宁区,4,320400
-320404,钟楼区,4,320400
-320411,新北区,4,320400
-320412,武进区,4,320400
-320413,金坛区,4,320400
-320481,溧阳市,4,320400
-320505,虎丘区,4,320500
-320506,吴中区,4,320500
-320507,相城区,4,320500
-320508,姑苏区,4,320500
-320509,吴江区,4,320500
-320571,苏州工业园区,4,320500
-320581,常熟市,4,320500
-320582,张家港市,4,320500
-320583,昆山市,4,320500
-320585,太仓市,4,320500
-320612,通州区,4,320600
-320613,崇川区,4,320600
-320614,海门区,4,320600
-320623,如东县,4,320600
-320671,南通经济技术开发区,4,320600
-320681,启东市,4,320600
-320682,如皋市,4,320600
-320685,海安市,4,320600
-320703,连云区,4,320700
-320706,海州区,4,320700
-320707,赣榆区,4,320700
-320722,东海县,4,320700
-320723,灌云县,4,320700
-320724,灌南县,4,320700
-320771,连云港经济技术开发区,4,320700
-320772,连云港高新技术产业开发区,4,320700
-320803,淮安区,4,320800
-320804,淮阴区,4,320800
-320812,清江浦区,4,320800
-320813,洪泽区,4,320800
-320826,涟水县,4,320800
-320830,盱眙县,4,320800
-320831,金湖县,4,320800
-320871,淮安经济技术开发区,4,320800
-320902,亭湖区,4,320900
-320903,盐都区,4,320900
-320904,大丰区,4,320900
-320921,响水县,4,320900
-320922,滨海县,4,320900
-320923,阜宁县,4,320900
-320924,射阳县,4,320900
-320925,建湖县,4,320900
-320971,盐城经济技术开发区,4,320900
-320981,东台市,4,320900
-321002,广陵区,4,321000
-321003,邗江区,4,321000
-321012,江都区,4,321000
-321023,宝应县,4,321000
-321071,扬州经济技术开发区,4,321000
-321081,仪征市,4,321000
-321084,高邮市,4,321000
-321102,京口区,4,321100
-321111,润州区,4,321100
-321112,丹徒区,4,321100
-321171,镇江新区,4,321100
-321181,丹阳市,4,321100
-321182,扬中市,4,321100
-321183,句容市,4,321100
-321202,海陵区,4,321200
-321203,高港区,4,321200
-321204,姜堰区,4,321200
-321271,泰州医药高新技术产业开发区,4,321200
-321281,兴化市,4,321200
-321282,靖江市,4,321200
-321283,泰兴市,4,321200
-321302,宿城区,4,321300
-321311,宿豫区,4,321300
-321322,沭阳县,4,321300
-321323,泗阳县,4,321300
-321324,泗洪县,4,321300
-321371,宿迁经济技术开发区,4,321300
-330102,上城区,4,330100
-330105,拱墅区,4,330100
-330106,西湖区,4,330100
-330108,滨江区,4,330100
-330109,萧山区,4,330100
-330110,余杭区,4,330100
-330111,富阳区,4,330100
-330112,临安区,4,330100
-330113,临平区,4,330100
-330114,钱塘区,4,330100
-330122,桐庐县,4,330100
-330127,淳安县,4,330100
-330182,建德市,4,330100
-330203,海曙区,4,330200
-330205,江北区,4,330200
-330206,北仑区,4,330200
-330211,镇海区,4,330200
-330212,鄞州区,4,330200
-330213,奉化区,4,330200
-330225,象山县,4,330200
-330226,宁海县,4,330200
-330281,余姚市,4,330200
-330282,慈溪市,4,330200
-330302,鹿城区,4,330300
-330303,龙湾区,4,330300
-330304,瓯海区,4,330300
-330305,洞头区,4,330300
-330324,永嘉县,4,330300
-330326,平阳县,4,330300
-330327,苍南县,4,330300
-330328,文成县,4,330300
-330329,泰顺县,4,330300
-330371,温州经济技术开发区,4,330300
-330381,瑞安市,4,330300
-330382,乐清市,4,330300
-330383,龙港市,4,330300
-330402,南湖区,4,330400
-330411,秀洲区,4,330400
-330421,嘉善县,4,330400
-330424,海盐县,4,330400
-330481,海宁市,4,330400
-330482,平湖市,4,330400
-330483,桐乡市,4,330400
-330502,吴兴区,4,330500
-330503,南浔区,4,330500
-330521,德清县,4,330500
-330522,长兴县,4,330500
-330523,安吉县,4,330500
-330602,越城区,4,330600
-330603,柯桥区,4,330600
-330604,上虞区,4,330600
-330624,新昌县,4,330600
-330681,诸暨市,4,330600
-330683,嵊州市,4,330600
-330702,婺城区,4,330700
-330703,金东区,4,330700
-330723,武义县,4,330700
-330726,浦江县,4,330700
-330727,磐安县,4,330700
-330781,兰溪市,4,330700
-330782,义乌市,4,330700
-330783,东阳市,4,330700
-330784,永康市,4,330700
-330802,柯城区,4,330800
-330803,衢江区,4,330800
-330822,常山县,4,330800
-330824,开化县,4,330800
-330825,龙游县,4,330800
-330881,江山市,4,330800
-330902,定海区,4,330900
-330903,普陀区,4,330900
-330921,岱山县,4,330900
-330922,嵊泗县,4,330900
-331002,椒江区,4,331000
-331003,黄岩区,4,331000
-331004,路桥区,4,331000
-331022,三门县,4,331000
-331023,天台县,4,331000
-331024,仙居县,4,331000
-331081,温岭市,4,331000
-331082,临海市,4,331000
-331083,玉环市,4,331000
-331102,莲都区,4,331100
-331121,青田县,4,331100
-331122,缙云县,4,331100
-331123,遂昌县,4,331100
-331124,松阳县,4,331100
-331125,云和县,4,331100
-331126,庆元县,4,331100
-331127,景宁畲族自治县,4,331100
-331181,龙泉市,4,331100
-340102,瑶海区,4,340100
-340103,庐阳区,4,340100
-340104,蜀山区,4,340100
-340111,包河区,4,340100
-340121,长丰县,4,340100
-340122,肥东县,4,340100
-340123,肥西县,4,340100
-340124,庐江县,4,340100
-340171,合肥高新技术产业开发区,4,340100
-340172,合肥经济技术开发区,4,340100
-340173,合肥新站高新技术产业开发区,4,340100
-340181,巢湖市,4,340100
-340202,镜湖区,4,340200
-340207,鸠江区,4,340200
-340209,弋江区,4,340200
-340210,湾沚区,4,340200
-340212,繁昌区,4,340200
-340223,南陵县,4,340200
-340271,芜湖经济技术开发区,4,340200
-340272,安徽芜湖三山经济开发区,4,340200
-340281,无为市,4,340200
-340302,龙子湖区,4,340300
-340303,蚌山区,4,340300
-340304,禹会区,4,340300
-340311,淮上区,4,340300
-340321,怀远县,4,340300
-340322,五河县,4,340300
-340323,固镇县,4,340300
-340371,蚌埠市高新技术开发区,4,340300
-340372,蚌埠市经济开发区,4,340300
-340402,大通区,4,340400
-340403,田家庵区,4,340400
-340404,谢家集区,4,340400
-340405,八公山区,4,340400
-340406,潘集区,4,340400
-340421,凤台县,4,340400
-340422,寿县,4,340400
-340503,花山区,4,340500
-340504,雨山区,4,340500
-340506,博望区,4,340500
-340521,当涂县,4,340500
-340522,含山县,4,340500
-340523,和县,4,340500
-340602,杜集区,4,340600
-340603,相山区,4,340600
-340604,烈山区,4,340600
-340621,濉溪县,4,340600
-340705,铜官区,4,340700
-340706,义安区,4,340700
-340711,郊区,4,340700
-340722,枞阳县,4,340700
-340802,迎江区,4,340800
-340803,大观区,4,340800
-340811,宜秀区,4,340800
-340822,怀宁县,4,340800
-340825,太湖县,4,340800
-340826,宿松县,4,340800
-340827,望江县,4,340800
-340828,岳西县,4,340800
-340871,安徽安庆经济开发区,4,340800
-340881,桐城市,4,340800
-340882,潜山市,4,340800
-341002,屯溪区,4,341000
-341003,黄山区,4,341000
-341004,徽州区,4,341000
-341021,歙县,4,341000
-341022,休宁县,4,341000
-341023,黟县,4,341000
-341024,祁门县,4,341000
-341102,琅琊区,4,341100
-341103,南谯区,4,341100
-341122,来安县,4,341100
-341124,全椒县,4,341100
-341125,定远县,4,341100
-341126,凤阳县,4,341100
-341171,中新苏滁高新技术产业开发区,4,341100
-341172,滁州经济技术开发区,4,341100
-341181,天长市,4,341100
-341182,明光市,4,341100
-341202,颍州区,4,341200
-341203,颍东区,4,341200
-341204,颍泉区,4,341200
-341221,临泉县,4,341200
-341222,太和县,4,341200
-341225,阜南县,4,341200
-341226,颍上县,4,341200
-341271,阜阳合肥现代产业园区,4,341200
-341272,阜阳经济技术开发区,4,341200
-341282,界首市,4,341200
-341302,埇桥区,4,341300
-341321,砀山县,4,341300
-341322,萧县,4,341300
-341323,灵璧县,4,341300
-341324,泗县,4,341300
-341371,宿州马鞍山现代产业园区,4,341300
-341372,宿州经济技术开发区,4,341300
-341502,金安区,4,341500
-341503,裕安区,4,341500
-341504,叶集区,4,341500
-341522,霍邱县,4,341500
-341523,舒城县,4,341500
-341524,金寨县,4,341500
-341525,霍山县,4,341500
-341602,谯城区,4,341600
-341621,涡阳县,4,341600
-341622,蒙城县,4,341600
-341623,利辛县,4,341600
-341702,贵池区,4,341700
-341721,东至县,4,341700
-341722,石台县,4,341700
-341723,青阳县,4,341700
-341802,宣州区,4,341800
-341821,郎溪县,4,341800
-341823,泾县,4,341800
-341824,绩溪县,4,341800
-341825,旌德县,4,341800
-341871,宣城市经济开发区,4,341800
-341881,宁国市,4,341800
-341882,广德市,4,341800
-350102,鼓楼区,4,350100
-350103,台江区,4,350100
-350104,仓山区,4,350100
-350105,马尾区,4,350100
-350111,晋安区,4,350100
-350112,长乐区,4,350100
-350121,闽侯县,4,350100
-350122,连江县,4,350100
-350123,罗源县,4,350100
-350124,闽清县,4,350100
-350125,永泰县,4,350100
-350128,平潭县,4,350100
-350181,福清市,4,350100
-350203,思明区,4,350200
-350205,海沧区,4,350200
-350206,湖里区,4,350200
-350211,集美区,4,350200
-350212,同安区,4,350200
-350213,翔安区,4,350200
-350302,城厢区,4,350300
-350303,涵江区,4,350300
-350304,荔城区,4,350300
-350305,秀屿区,4,350300
-350322,仙游县,4,350300
-350404,三元区,4,350400
-350405,沙县区,4,350400
-350421,明溪县,4,350400
-350423,清流县,4,350400
-350424,宁化县,4,350400
-350425,大田县,4,350400
-350426,尤溪县,4,350400
-350428,将乐县,4,350400
-350429,泰宁县,4,350400
-350430,建宁县,4,350400
-350481,永安市,4,350400
-350502,鲤城区,4,350500
-350503,丰泽区,4,350500
-350504,洛江区,4,350500
-350505,泉港区,4,350500
-350521,惠安县,4,350500
-350524,安溪县,4,350500
-350525,永春县,4,350500
-350526,德化县,4,350500
-350527,金门县,4,350500
-350581,石狮市,4,350500
-350582,晋江市,4,350500
-350583,南安市,4,350500
-350602,芗城区,4,350600
-350603,龙文区,4,350600
-350604,龙海区,4,350600
-350605,长泰区,4,350600
-350622,云霄县,4,350600
-350623,漳浦县,4,350600
-350624,诏安县,4,350600
-350626,东山县,4,350600
-350627,南靖县,4,350600
-350628,平和县,4,350600
-350629,华安县,4,350600
-350702,延平区,4,350700
-350703,建阳区,4,350700
-350721,顺昌县,4,350700
-350722,浦城县,4,350700
-350723,光泽县,4,350700
-350724,松溪县,4,350700
-350725,政和县,4,350700
-350781,邵武市,4,350700
-350782,武夷山市,4,350700
-350783,建瓯市,4,350700
-350802,新罗区,4,350800
-350803,永定区,4,350800
-350821,长汀县,4,350800
-350823,上杭县,4,350800
-350824,武平县,4,350800
-350825,连城县,4,350800
-350881,漳平市,4,350800
-350902,蕉城区,4,350900
-350921,霞浦县,4,350900
-350922,古田县,4,350900
-350923,屏南县,4,350900
-350924,寿宁县,4,350900
-350925,周宁县,4,350900
-350926,柘荣县,4,350900
-350981,福安市,4,350900
-350982,福鼎市,4,350900
-360102,东湖区,4,360100
-360103,西湖区,4,360100
-360104,青云谱区,4,360100
-360111,青山湖区,4,360100
-360112,新建区,4,360100
-360113,红谷滩区,4,360100
-360121,南昌县,4,360100
-360123,安义县,4,360100
-360124,进贤县,4,360100
-360202,昌江区,4,360200
-360203,珠山区,4,360200
-360222,浮梁县,4,360200
-360281,乐平市,4,360200
-360302,安源区,4,360300
-360313,湘东区,4,360300
-360321,莲花县,4,360300
-360322,上栗县,4,360300
-360323,芦溪县,4,360300
-360402,濂溪区,4,360400
-360403,浔阳区,4,360400
-360404,柴桑区,4,360400
-360423,武宁县,4,360400
-360424,修水县,4,360400
-360425,永修县,4,360400
-360426,德安县,4,360400
-360428,都昌县,4,360400
-360429,湖口县,4,360400
-360430,彭泽县,4,360400
-360481,瑞昌市,4,360400
-360482,共青城市,4,360400
-360483,庐山市,4,360400
-360502,渝水区,4,360500
-360521,分宜县,4,360500
-360602,月湖区,4,360600
-360603,余江区,4,360600
-360681,贵溪市,4,360600
-360702,章贡区,4,360700
-360703,南康区,4,360700
-360704,赣县区,4,360700
-360722,信丰县,4,360700
-360723,大余县,4,360700
-360724,上犹县,4,360700
-360725,崇义县,4,360700
-360726,安远县,4,360700
-360728,定南县,4,360700
-360729,全南县,4,360700
-360730,宁都县,4,360700
-360731,于都县,4,360700
-360732,兴国县,4,360700
-360733,会昌县,4,360700
-360734,寻乌县,4,360700
-360735,石城县,4,360700
-360781,瑞金市,4,360700
-360783,龙南市,4,360700
-360802,吉州区,4,360800
-360803,青原区,4,360800
-360821,吉安县,4,360800
-360822,吉水县,4,360800
-360823,峡江县,4,360800
-360824,新干县,4,360800
-360825,永丰县,4,360800
-360826,泰和县,4,360800
-360827,遂川县,4,360800
-360828,万安县,4,360800
-360829,安福县,4,360800
-360830,永新县,4,360800
-360881,井冈山市,4,360800
-360902,袁州区,4,360900
-360921,奉新县,4,360900
-360922,万载县,4,360900
-360923,上高县,4,360900
-360924,宜丰县,4,360900
-360925,靖安县,4,360900
-360926,铜鼓县,4,360900
-360981,丰城市,4,360900
-360982,樟树市,4,360900
-360983,高安市,4,360900
-361002,临川区,4,361000
-361003,东乡区,4,361000
-361021,南城县,4,361000
-361022,黎川县,4,361000
-361023,南丰县,4,361000
-361024,崇仁县,4,361000
-361025,乐安县,4,361000
-361026,宜黄县,4,361000
-361027,金溪县,4,361000
-361028,资溪县,4,361000
-361030,广昌县,4,361000
-361102,信州区,4,361100
-361103,广丰区,4,361100
-361104,广信区,4,361100
-361123,玉山县,4,361100
-361124,铅山县,4,361100
-361125,横峰县,4,361100
-361126,弋阳县,4,361100
-361127,余干县,4,361100
-361128,鄱阳县,4,361100
-361129,万年县,4,361100
-361130,婺源县,4,361100
-361181,德兴市,4,361100
-370102,历下区,4,370100
-370103,市中区,4,370100
-370104,槐荫区,4,370100
-370105,天桥区,4,370100
-370112,历城区,4,370100
-370113,长清区,4,370100
-370114,章丘区,4,370100
-370115,济阳区,4,370100
-370116,莱芜区,4,370100
-370117,钢城区,4,370100
-370124,平阴县,4,370100
-370126,商河县,4,370100
-370171,济南高新技术产业开发区,4,370100
-370202,市南区,4,370200
-370203,市北区,4,370200
-370211,黄岛区,4,370200
-370212,崂山区,4,370200
-370213,李沧区,4,370200
-370214,城阳区,4,370200
-370215,即墨区,4,370200
-370271,青岛高新技术产业开发区,4,370200
-370281,胶州市,4,370200
-370283,平度市,4,370200
-370285,莱西市,4,370200
-370302,淄川区,4,370300
-370303,张店区,4,370300
-370304,博山区,4,370300
-370305,临淄区,4,370300
-370306,周村区,4,370300
-370321,桓台县,4,370300
-370322,高青县,4,370300
-370323,沂源县,4,370300
-370402,市中区,4,370400
-370403,薛城区,4,370400
-370404,峄城区,4,370400
-370405,台儿庄区,4,370400
-370406,山亭区,4,370400
-370481,滕州市,4,370400
-370502,东营区,4,370500
-370503,河口区,4,370500
-370505,垦利区,4,370500
-370522,利津县,4,370500
-370523,广饶县,4,370500
-370571,东营经济技术开发区,4,370500
-370572,东营港经济开发区,4,370500
-370602,芝罘区,4,370600
-370611,福山区,4,370600
-370612,牟平区,4,370600
-370613,莱山区,4,370600
-370614,蓬莱区,4,370600
-370671,烟台高新技术产业开发区,4,370600
-370672,烟台经济技术开发区,4,370600
-370681,龙口市,4,370600
-370682,莱阳市,4,370600
-370683,莱州市,4,370600
-370685,招远市,4,370600
-370686,栖霞市,4,370600
-370687,海阳市,4,370600
-370702,潍城区,4,370700
-370703,寒亭区,4,370700
-370704,坊子区,4,370700
-370705,奎文区,4,370700
-370724,临朐县,4,370700
-370725,昌乐县,4,370700
-370772,潍坊滨海经济技术开发区,4,370700
-370781,青州市,4,370700
-370782,诸城市,4,370700
-370783,寿光市,4,370700
-370784,安丘市,4,370700
-370785,高密市,4,370700
-370786,昌邑市,4,370700
-370811,任城区,4,370800
-370812,兖州区,4,370800
-370826,微山县,4,370800
-370827,鱼台县,4,370800
-370828,金乡县,4,370800
-370829,嘉祥县,4,370800
-370830,汶上县,4,370800
-370831,泗水县,4,370800
-370832,梁山县,4,370800
-370871,济宁高新技术产业开发区,4,370800
-370881,曲阜市,4,370800
-370883,邹城市,4,370800
-370902,泰山区,4,370900
-370911,岱岳区,4,370900
-370921,宁阳县,4,370900
-370923,东平县,4,370900
-370982,新泰市,4,370900
-370983,肥城市,4,370900
-371002,环翠区,4,371000
-371003,文登区,4,371000
-371071,威海火炬高技术产业开发区,4,371000
-371072,威海经济技术开发区,4,371000
-371073,威海临港经济技术开发区,4,371000
-371082,荣成市,4,371000
-371083,乳山市,4,371000
-371102,东港区,4,371100
-371103,岚山区,4,371100
-371121,五莲县,4,371100
-371122,莒县,4,371100
-371171,日照经济技术开发区,4,371100
-371302,兰山区,4,371300
-371311,罗庄区,4,371300
-371312,河东区,4,371300
-371321,沂南县,4,371300
-371322,郯城县,4,371300
-371323,沂水县,4,371300
-371324,兰陵县,4,371300
-371325,费县,4,371300
-371326,平邑县,4,371300
-371327,莒南县,4,371300
-371328,蒙阴县,4,371300
-371329,临沭县,4,371300
-371371,临沂高新技术产业开发区,4,371300
-371402,德城区,4,371400
-371403,陵城区,4,371400
-371422,宁津县,4,371400
-371423,庆云县,4,371400
-371424,临邑县,4,371400
-371425,齐河县,4,371400
-371426,平原县,4,371400
-371427,夏津县,4,371400
-371428,武城县,4,371400
-371471,德州经济技术开发区,4,371400
-371472,德州运河经济开发区,4,371400
-371481,乐陵市,4,371400
-371482,禹城市,4,371400
-371502,东昌府区,4,371500
-371503,茌平区,4,371500
-371521,阳谷县,4,371500
-371522,莘县,4,371500
-371524,东阿县,4,371500
-371525,冠县,4,371500
-371526,高唐县,4,371500
-371581,临清市,4,371500
-371602,滨城区,4,371600
-371603,沾化区,4,371600
-371621,惠民县,4,371600
-371622,阳信县,4,371600
-371623,无棣县,4,371600
-371625,博兴县,4,371600
-371681,邹平市,4,371600
-371702,牡丹区,4,371700
-371703,定陶区,4,371700
-371721,曹县,4,371700
-371722,单县,4,371700
-371723,成武县,4,371700
-371724,巨野县,4,371700
-371725,郓城县,4,371700
-371726,鄄城县,4,371700
-371728,东明县,4,371700
-371771,菏泽经济技术开发区,4,371700
-371772,菏泽高新技术开发区,4,371700
-410102,中原区,4,410100
-410103,二七区,4,410100
-410104,管城回族区,4,410100
-410105,金水区,4,410100
-410106,上街区,4,410100
-410108,惠济区,4,410100
-410122,中牟县,4,410100
-410171,郑州经济技术开发区,4,410100
-410172,郑州高新技术产业开发区,4,410100
-410173,郑州航空港经济综合实验区,4,410100
-410181,巩义市,4,410100
-410182,荥阳市,4,410100
-410183,新密市,4,410100
-410184,新郑市,4,410100
-410185,登封市,4,410100
-410202,龙亭区,4,410200
-410203,顺河回族区,4,410200
-410204,鼓楼区,4,410200
-410205,禹王台区,4,410200
-410212,祥符区,4,410200
-410221,杞县,4,410200
-410222,通许县,4,410200
-410223,尉氏县,4,410200
-410225,兰考县,4,410200
-410302,老城区,4,410300
-410303,西工区,4,410300
-410304,瀍河回族区,4,410300
-410305,涧西区,4,410300
-410307,偃师区,4,410300
-410308,孟津区,4,410300
-410311,洛龙区,4,410300
-410323,新安县,4,410300
-410324,栾川县,4,410300
-410325,嵩县,4,410300
-410326,汝阳县,4,410300
-410327,宜阳县,4,410300
-410328,洛宁县,4,410300
-410329,伊川县,4,410300
-410371,洛阳高新技术产业开发区,4,410300
-410402,新华区,4,410400
-410403,卫东区,4,410400
-410404,石龙区,4,410400
-410411,湛河区,4,410400
-410421,宝丰县,4,410400
-410422,叶县,4,410400
-410423,鲁山县,4,410400
-410425,郏县,4,410400
-410471,平顶山高新技术产业开发区,4,410400
-410472,平顶山市城乡一体化示范区,4,410400
-410481,舞钢市,4,410400
-410482,汝州市,4,410400
-410502,文峰区,4,410500
-410503,北关区,4,410500
-410505,殷都区,4,410500
-410506,龙安区,4,410500
-410522,安阳县,4,410500
-410523,汤阴县,4,410500
-410526,滑县,4,410500
-410527,内黄县,4,410500
-410571,安阳高新技术产业开发区,4,410500
-410581,林州市,4,410500
-410602,鹤山区,4,410600
-410603,山城区,4,410600
-410611,淇滨区,4,410600
-410621,浚县,4,410600
-410622,淇县,4,410600
-410671,鹤壁经济技术开发区,4,410600
-410702,红旗区,4,410700
-410703,卫滨区,4,410700
-410704,凤泉区,4,410700
-410711,牧野区,4,410700
-410721,新乡县,4,410700
-410724,获嘉县,4,410700
-410725,原阳县,4,410700
-410726,延津县,4,410700
-410727,封丘县,4,410700
-410771,新乡高新技术产业开发区,4,410700
-410772,新乡经济技术开发区,4,410700
-410773,新乡市平原城乡一体化示范区,4,410700
-410781,卫辉市,4,410700
-410782,辉县市,4,410700
-410783,长垣市,4,410700
-410802,解放区,4,410800
-410803,中站区,4,410800
-410804,马村区,4,410800
-410811,山阳区,4,410800
-410821,修武县,4,410800
-410822,博爱县,4,410800
-410823,武陟县,4,410800
-410825,温县,4,410800
-410871,焦作城乡一体化示范区,4,410800
-410882,沁阳市,4,410800
-410883,孟州市,4,410800
-410902,华龙区,4,410900
-410922,清丰县,4,410900
-410923,南乐县,4,410900
-410926,范县,4,410900
-410927,台前县,4,410900
-410928,濮阳县,4,410900
-410971,河南濮阳工业园区,4,410900
-410972,濮阳经济技术开发区,4,410900
-411002,魏都区,4,411000
-411003,建安区,4,411000
-411024,鄢陵县,4,411000
-411025,襄城县,4,411000
-411071,许昌经济技术开发区,4,411000
-411081,禹州市,4,411000
-411082,长葛市,4,411000
-411102,源汇区,4,411100
-411103,郾城区,4,411100
-411104,召陵区,4,411100
-411121,舞阳县,4,411100
-411122,临颍县,4,411100
-411171,漯河经济技术开发区,4,411100
-411202,湖滨区,4,411200
-411203,陕州区,4,411200
-411221,渑池县,4,411200
-411224,卢氏县,4,411200
-411271,河南三门峡经济开发区,4,411200
-411281,义马市,4,411200
-411282,灵宝市,4,411200
-411302,宛城区,4,411300
-411303,卧龙区,4,411300
-411321,南召县,4,411300
-411322,方城县,4,411300
-411323,西峡县,4,411300
-411324,镇平县,4,411300
-411325,内乡县,4,411300
-411326,淅川县,4,411300
-411327,社旗县,4,411300
-411328,唐河县,4,411300
-411329,新野县,4,411300
-411330,桐柏县,4,411300
-411371,南阳高新技术产业开发区,4,411300
-411372,南阳市城乡一体化示范区,4,411300
-411381,邓州市,4,411300
-411402,梁园区,4,411400
-411403,睢阳区,4,411400
-411421,民权县,4,411400
-411422,睢县,4,411400
-411423,宁陵县,4,411400
-411424,柘城县,4,411400
-411425,虞城县,4,411400
-411426,夏邑县,4,411400
-411471,豫东综合物流产业聚集区,4,411400
-411472,河南商丘经济开发区,4,411400
-411481,永城市,4,411400
-411502,浉河区,4,411500
-411503,平桥区,4,411500
-411521,罗山县,4,411500
-411522,光山县,4,411500
-411523,新县,4,411500
-411524,商城县,4,411500
-411525,固始县,4,411500
-411526,潢川县,4,411500
-411527,淮滨县,4,411500
-411528,息县,4,411500
-411571,信阳高新技术产业开发区,4,411500
-411602,川汇区,4,411600
-411603,淮阳区,4,411600
-411621,扶沟县,4,411600
-411622,西华县,4,411600
-411623,商水县,4,411600
-411624,沈丘县,4,411600
-411625,郸城县,4,411600
-411627,太康县,4,411600
-411628,鹿邑县,4,411600
-411671,河南周口经济开发区,4,411600
-411681,项城市,4,411600
-411702,驿城区,4,411700
-411721,西平县,4,411700
-411722,上蔡县,4,411700
-411723,平舆县,4,411700
-411724,正阳县,4,411700
-411725,确山县,4,411700
-411726,泌阳县,4,411700
-411727,汝南县,4,411700
-411728,遂平县,4,411700
-411729,新蔡县,4,411700
-411771,河南驻马店经济开发区,4,411700
-419001,济源市,4,419000
-420102,江岸区,4,420100
-420103,江汉区,4,420100
-420104,硚口区,4,420100
-420105,汉阳区,4,420100
-420106,武昌区,4,420100
-420107,青山区,4,420100
-420111,洪山区,4,420100
-420112,东西湖区,4,420100
-420113,汉南区,4,420100
-420114,蔡甸区,4,420100
-420115,江夏区,4,420100
-420116,黄陂区,4,420100
-420117,新洲区,4,420100
-420202,黄石港区,4,420200
-420203,西塞山区,4,420200
-420204,下陆区,4,420200
-420205,铁山区,4,420200
-420222,阳新县,4,420200
-420281,大冶市,4,420200
-420302,茅箭区,4,420300
-420303,张湾区,4,420300
-420304,郧阳区,4,420300
-420322,郧西县,4,420300
-420323,竹山县,4,420300
-420324,竹溪县,4,420300
-420325,房县,4,420300
-420381,丹江口市,4,420300
-420502,西陵区,4,420500
-420503,伍家岗区,4,420500
-420504,点军区,4,420500
-420505,猇亭区,4,420500
-420506,夷陵区,4,420500
-420525,远安县,4,420500
-420526,兴山县,4,420500
-420527,秭归县,4,420500
-420528,长阳土家族自治县,4,420500
-420529,五峰土家族自治县,4,420500
-420581,宜都市,4,420500
-420582,当阳市,4,420500
-420583,枝江市,4,420500
-420602,襄城区,4,420600
-420606,樊城区,4,420600
-420607,襄州区,4,420600
-420624,南漳县,4,420600
-420625,谷城县,4,420600
-420626,保康县,4,420600
-420682,老河口市,4,420600
-420683,枣阳市,4,420600
-420684,宜城市,4,420600
-420702,梁子湖区,4,420700
-420703,华容区,4,420700
-420704,鄂城区,4,420700
-420802,东宝区,4,420800
-420804,掇刀区,4,420800
-420822,沙洋县,4,420800
-420881,钟祥市,4,420800
-420882,京山市,4,420800
-420902,孝南区,4,420900
-420921,孝昌县,4,420900
-420922,大悟县,4,420900
-420923,云梦县,4,420900
-420981,应城市,4,420900
-420982,安陆市,4,420900
-420984,汉川市,4,420900
-421002,沙市区,4,421000
-421003,荆州区,4,421000
-421022,公安县,4,421000
-421024,江陵县,4,421000
-421071,荆州经济技术开发区,4,421000
-421081,石首市,4,421000
-421083,洪湖市,4,421000
-421087,松滋市,4,421000
-421088,监利市,4,421000
-421102,黄州区,4,421100
-421121,团风县,4,421100
-421122,红安县,4,421100
-421123,罗田县,4,421100
-421124,英山县,4,421100
-421125,浠水县,4,421100
-421126,蕲春县,4,421100
-421127,黄梅县,4,421100
-421171,龙感湖管理区,4,421100
-421181,麻城市,4,421100
-421182,武穴市,4,421100
-421202,咸安区,4,421200
-421221,嘉鱼县,4,421200
-421222,通城县,4,421200
-421223,崇阳县,4,421200
-421224,通山县,4,421200
-421281,赤壁市,4,421200
-421303,曾都区,4,421300
-421321,随县,4,421300
-421381,广水市,4,421300
-422801,恩施市,4,422800
-422802,利川市,4,422800
-422822,建始县,4,422800
-422823,巴东县,4,422800
-422825,宣恩县,4,422800
-422826,咸丰县,4,422800
-422827,来凤县,4,422800
-422828,鹤峰县,4,422800
-429004,仙桃市,4,429000
-429005,潜江市,4,429000
-429006,天门市,4,429000
-429021,神农架林区,4,429000
-430102,芙蓉区,4,430100
-430103,天心区,4,430100
-430104,岳麓区,4,430100
-430105,开福区,4,430100
-430111,雨花区,4,430100
-430112,望城区,4,430100
-430121,长沙县,4,430100
-430181,浏阳市,4,430100
-430182,宁乡市,4,430100
-430202,荷塘区,4,430200
-430203,芦淞区,4,430200
-430204,石峰区,4,430200
-430211,天元区,4,430200
-430212,渌口区,4,430200
-430223,攸县,4,430200
-430224,茶陵县,4,430200
-430225,炎陵县,4,430200
-430271,云龙示范区,4,430200
-430281,醴陵市,4,430200
-430302,雨湖区,4,430300
-430304,岳塘区,4,430300
-430321,湘潭县,4,430300
-430371,湖南湘潭高新技术产业园区,4,430300
-430372,湘潭昭山示范区,4,430300
-430373,湘潭九华示范区,4,430300
-430381,湘乡市,4,430300
-430382,韶山市,4,430300
-430405,珠晖区,4,430400
-430406,雁峰区,4,430400
-430407,石鼓区,4,430400
-430408,蒸湘区,4,430400
-430412,南岳区,4,430400
-430421,衡阳县,4,430400
-430422,衡南县,4,430400
-430423,衡山县,4,430400
-430424,衡东县,4,430400
-430426,祁东县,4,430400
-430471,衡阳综合保税区,4,430400
-430472,湖南衡阳高新技术产业园区,4,430400
-430473,湖南衡阳松木经济开发区,4,430400
-430481,耒阳市,4,430400
-430482,常宁市,4,430400
-430502,双清区,4,430500
-430503,大祥区,4,430500
-430511,北塔区,4,430500
-430522,新邵县,4,430500
-430523,邵阳县,4,430500
-430524,隆回县,4,430500
-430525,洞口县,4,430500
-430527,绥宁县,4,430500
-430528,新宁县,4,430500
-430529,城步苗族自治县,4,430500
-430581,武冈市,4,430500
-430582,邵东市,4,430500
-430602,岳阳楼区,4,430600
-430603,云溪区,4,430600
-430611,君山区,4,430600
-430621,岳阳县,4,430600
-430623,华容县,4,430600
-430624,湘阴县,4,430600
-430626,平江县,4,430600
-430671,岳阳市屈原管理区,4,430600
-430681,汨罗市,4,430600
-430682,临湘市,4,430600
-430702,武陵区,4,430700
-430703,鼎城区,4,430700
-430721,安乡县,4,430700
-430722,汉寿县,4,430700
-430723,澧县,4,430700
-430724,临澧县,4,430700
-430725,桃源县,4,430700
-430726,石门县,4,430700
-430771,常德市西洞庭管理区,4,430700
-430781,津市市,4,430700
-430802,永定区,4,430800
-430811,武陵源区,4,430800
-430821,慈利县,4,430800
-430822,桑植县,4,430800
-430902,资阳区,4,430900
-430903,赫山区,4,430900
-430921,南县,4,430900
-430922,桃江县,4,430900
-430923,安化县,4,430900
-430971,益阳市大通湖管理区,4,430900
-430972,湖南益阳高新技术产业园区,4,430900
-430981,沅江市,4,430900
-431002,北湖区,4,431000
-431003,苏仙区,4,431000
-431021,桂阳县,4,431000
-431022,宜章县,4,431000
-431023,永兴县,4,431000
-431024,嘉禾县,4,431000
-431025,临武县,4,431000
-431026,汝城县,4,431000
-431027,桂东县,4,431000
-431028,安仁县,4,431000
-431081,资兴市,4,431000
-431102,零陵区,4,431100
-431103,冷水滩区,4,431100
-431122,东安县,4,431100
-431123,双牌县,4,431100
-431124,道县,4,431100
-431125,江永县,4,431100
-431126,宁远县,4,431100
-431127,蓝山县,4,431100
-431128,新田县,4,431100
-431129,江华瑶族自治县,4,431100
-431171,永州经济技术开发区,4,431100
-431173,永州市回龙圩管理区,4,431100
-431181,祁阳市,4,431100
-431202,鹤城区,4,431200
-431221,中方县,4,431200
-431222,沅陵县,4,431200
-431223,辰溪县,4,431200
-431224,溆浦县,4,431200
-431225,会同县,4,431200
-431226,麻阳苗族自治县,4,431200
-431227,新晃侗族自治县,4,431200
-431228,芷江侗族自治县,4,431200
-431229,靖州苗族侗族自治县,4,431200
-431230,通道侗族自治县,4,431200
-431271,怀化市洪江管理区,4,431200
-431281,洪江市,4,431200
-431302,娄星区,4,431300
-431321,双峰县,4,431300
-431322,新化县,4,431300
-431381,冷水江市,4,431300
-431382,涟源市,4,431300
-433101,吉首市,4,433100
-433122,泸溪县,4,433100
-433123,凤凰县,4,433100
-433124,花垣县,4,433100
-433125,保靖县,4,433100
-433126,古丈县,4,433100
-433127,永顺县,4,433100
-433130,龙山县,4,433100
-440103,荔湾区,4,440100
-440104,越秀区,4,440100
-440105,海珠区,4,440100
-440106,天河区,4,440100
-440111,白云区,4,440100
-440112,黄埔区,4,440100
-440113,番禺区,4,440100
-440114,花都区,4,440100
-440115,南沙区,4,440100
-440117,从化区,4,440100
-440118,增城区,4,440100
-440203,武江区,4,440200
-440204,浈江区,4,440200
-440205,曲江区,4,440200
-440222,始兴县,4,440200
-440224,仁化县,4,440200
-440229,翁源县,4,440200
-440232,乳源瑶族自治县,4,440200
-440233,新丰县,4,440200
-440281,乐昌市,4,440200
-440282,南雄市,4,440200
-440303,罗湖区,4,440300
-440304,福田区,4,440300
-440305,南山区,4,440300
-440306,宝安区,4,440300
-440307,龙岗区,4,440300
-440308,盐田区,4,440300
-440309,龙华区,4,440300
-440310,坪山区,4,440300
-440311,光明区,4,440300
-440402,香洲区,4,440400
-440403,斗门区,4,440400
-440404,金湾区,4,440400
-440507,龙湖区,4,440500
-440511,金平区,4,440500
-440512,濠江区,4,440500
-440513,潮阳区,4,440500
-440514,潮南区,4,440500
-440515,澄海区,4,440500
-440523,南澳县,4,440500
-440604,禅城区,4,440600
-440605,南海区,4,440600
-440606,顺德区,4,440600
-440607,三水区,4,440600
-440608,高明区,4,440600
-440703,蓬江区,4,440700
-440704,江海区,4,440700
-440705,新会区,4,440700
-440781,台山市,4,440700
-440783,开平市,4,440700
-440784,鹤山市,4,440700
-440785,恩平市,4,440700
-440802,赤坎区,4,440800
-440803,霞山区,4,440800
-440804,坡头区,4,440800
-440811,麻章区,4,440800
-440823,遂溪县,4,440800
-440825,徐闻县,4,440800
-440881,廉江市,4,440800
-440882,雷州市,4,440800
-440883,吴川市,4,440800
-440902,茂南区,4,440900
-440904,电白区,4,440900
-440981,高州市,4,440900
-440982,化州市,4,440900
-440983,信宜市,4,440900
-441202,端州区,4,441200
-441203,鼎湖区,4,441200
-441204,高要区,4,441200
-441223,广宁县,4,441200
-441224,怀集县,4,441200
-441225,封开县,4,441200
-441226,德庆县,4,441200
-441284,四会市,4,441200
-441302,惠城区,4,441300
-441303,惠阳区,4,441300
-441322,博罗县,4,441300
-441323,惠东县,4,441300
-441324,龙门县,4,441300
-441402,梅江区,4,441400
-441403,梅县区,4,441400
-441422,大埔县,4,441400
-441423,丰顺县,4,441400
-441424,五华县,4,441400
-441426,平远县,4,441400
-441427,蕉岭县,4,441400
-441481,兴宁市,4,441400
-441502,城区,4,441500
-441521,海丰县,4,441500
-441523,陆河县,4,441500
-441581,陆丰市,4,441500
-441602,源城区,4,441600
-441621,紫金县,4,441600
-441622,龙川县,4,441600
-441623,连平县,4,441600
-441624,和平县,4,441600
-441625,东源县,4,441600
-441702,江城区,4,441700
-441704,阳东区,4,441700
-441721,阳西县,4,441700
-441781,阳春市,4,441700
-441802,清城区,4,441800
-441803,清新区,4,441800
-441821,佛冈县,4,441800
-441823,阳山县,4,441800
-441825,连山壮族瑶族自治县,4,441800
-441826,连南瑶族自治县,4,441800
-441881,英德市,4,441800
-441882,连州市,4,441800
-445102,湘桥区,4,445100
-445103,潮安区,4,445100
-445122,饶平县,4,445100
-445202,榕城区,4,445200
-445203,揭东区,4,445200
-445222,揭西县,4,445200
-445224,惠来县,4,445200
-445281,普宁市,4,445200
-445302,云城区,4,445300
-445303,云安区,4,445300
-445321,新兴县,4,445300
-445322,郁南县,4,445300
-445381,罗定市,4,445300
-450102,兴宁区,4,450100
-450103,青秀区,4,450100
-450105,江南区,4,450100
-450107,西乡塘区,4,450100
-450108,良庆区,4,450100
-450109,邕宁区,4,450100
-450110,武鸣区,4,450100
-450123,隆安县,4,450100
-450124,马山县,4,450100
-450125,上林县,4,450100
-450126,宾阳县,4,450100
-450181,横州市,4,450100
-450202,城中区,4,450200
-450203,鱼峰区,4,450200
-450204,柳南区,4,450200
-450205,柳北区,4,450200
-450206,柳江区,4,450200
-450222,柳城县,4,450200
-450223,鹿寨县,4,450200
-450224,融安县,4,450200
-450225,融水苗族自治县,4,450200
-450226,三江侗族自治县,4,450200
-450302,秀峰区,4,450300
-450303,叠彩区,4,450300
-450304,象山区,4,450300
-450305,七星区,4,450300
-450311,雁山区,4,450300
-450312,临桂区,4,450300
-450321,阳朔县,4,450300
-450323,灵川县,4,450300
-450324,全州县,4,450300
-450325,兴安县,4,450300
-450326,永福县,4,450300
-450327,灌阳县,4,450300
-450328,龙胜各族自治县,4,450300
-450329,资源县,4,450300
-450330,平乐县,4,450300
-450332,恭城瑶族自治县,4,450300
-450381,荔浦市,4,450300
-450403,万秀区,4,450400
-450405,长洲区,4,450400
-450406,龙圩区,4,450400
-450421,苍梧县,4,450400
-450422,藤县,4,450400
-450423,蒙山县,4,450400
-450481,岑溪市,4,450400
-450502,海城区,4,450500
-450503,银海区,4,450500
-450512,铁山港区,4,450500
-450521,合浦县,4,450500
-450602,港口区,4,450600
-450603,防城区,4,450600
-450621,上思县,4,450600
-450681,东兴市,4,450600
-450702,钦南区,4,450700
-450703,钦北区,4,450700
-450721,灵山县,4,450700
-450722,浦北县,4,450700
-450802,港北区,4,450800
-450803,港南区,4,450800
-450804,覃塘区,4,450800
-450821,平南县,4,450800
-450881,桂平市,4,450800
-450902,玉州区,4,450900
-450903,福绵区,4,450900
-450921,容县,4,450900
-450922,陆川县,4,450900
-450923,博白县,4,450900
-450924,兴业县,4,450900
-450981,北流市,4,450900
-451002,右江区,4,451000
-451003,田阳区,4,451000
-451022,田东县,4,451000
-451024,德保县,4,451000
-451026,那坡县,4,451000
-451027,凌云县,4,451000
-451028,乐业县,4,451000
-451029,田林县,4,451000
-451030,西林县,4,451000
-451031,隆林各族自治县,4,451000
-451081,靖西市,4,451000
-451082,平果市,4,451000
-451102,八步区,4,451100
-451103,平桂区,4,451100
-451121,昭平县,4,451100
-451122,钟山县,4,451100
-451123,富川瑶族自治县,4,451100
-451202,金城江区,4,451200
-451203,宜州区,4,451200
-451221,南丹县,4,451200
-451222,天峨县,4,451200
-451223,凤山县,4,451200
-451224,东兰县,4,451200
-451225,罗城仫佬族自治县,4,451200
-451226,环江毛南族自治县,4,451200
-451227,巴马瑶族自治县,4,451200
-451228,都安瑶族自治县,4,451200
-451229,大化瑶族自治县,4,451200
-451302,兴宾区,4,451300
-451321,忻城县,4,451300
-451322,象州县,4,451300
-451323,武宣县,4,451300
-451324,金秀瑶族自治县,4,451300
-451381,合山市,4,451300
-451402,江州区,4,451400
-451421,扶绥县,4,451400
-451422,宁明县,4,451400
-451423,龙州县,4,451400
-451424,大新县,4,451400
-451425,天等县,4,451400
-451481,凭祥市,4,451400
-460105,秀英区,4,460100
-460106,龙华区,4,460100
-460107,琼山区,4,460100
-460108,美兰区,4,460100
-460202,海棠区,4,460200
-460203,吉阳区,4,460200
-460204,天涯区,4,460200
-460205,崖州区,4,460200
-460321,西沙群岛,4,460300
-460322,南沙群岛,4,460300
-460323,中沙群岛的岛礁及其海域,4,460300
-469001,五指山市,4,469000
-469002,琼海市,4,469000
-469005,文昌市,4,469000
-469006,万宁市,4,469000
-469007,东方市,4,469000
-469021,定安县,4,469000
-469022,屯昌县,4,469000
-469023,澄迈县,4,469000
-469024,临高县,4,469000
-469025,白沙黎族自治县,4,469000
-469026,昌江黎族自治县,4,469000
-469027,乐东黎族自治县,4,469000
-469028,陵水黎族自治县,4,469000
-469029,保亭黎族苗族自治县,4,469000
-469030,琼中黎族苗族自治县,4,469000
-500101,万州区,4,500100
-500102,涪陵区,4,500100
-500103,渝中区,4,500100
-500104,大渡口区,4,500100
-500105,江北区,4,500100
-500106,沙坪坝区,4,500100
-500107,九龙坡区,4,500100
-500108,南岸区,4,500100
-500109,北碚区,4,500100
-500110,綦江区,4,500100
-500111,大足区,4,500100
-500112,渝北区,4,500100
-500113,巴南区,4,500100
-500114,黔江区,4,500100
-500115,长寿区,4,500100
-500116,江津区,4,500100
-500117,合川区,4,500100
-500118,永川区,4,500100
-500119,南川区,4,500100
-500120,璧山区,4,500100
-500151,铜梁区,4,500100
-500152,潼南区,4,500100
-500153,荣昌区,4,500100
-500154,开州区,4,500100
-500155,梁平区,4,500100
-500156,武隆区,4,500100
-500229,城口县,4,500100
-500230,丰都县,4,500100
-500231,垫江县,4,500100
-500233,忠县,4,500100
-500235,云阳县,4,500100
-500236,奉节县,4,500100
-500237,巫山县,4,500100
-500238,巫溪县,4,500100
-500240,石柱土家族自治县,4,500100
-500241,秀山土家族苗族自治县,4,500100
-500242,酉阳土家族苗族自治县,4,500100
-500243,彭水苗族土家族自治县,4,500100
-510104,锦江区,4,510100
-510105,青羊区,4,510100
-510106,金牛区,4,510100
-510107,武侯区,4,510100
-510108,成华区,4,510100
-510112,龙泉驿区,4,510100
-510113,青白江区,4,510100
-510114,新都区,4,510100
-510115,温江区,4,510100
-510116,双流区,4,510100
-510117,郫都区,4,510100
-510118,新津区,4,510100
-510121,金堂县,4,510100
-510129,大邑县,4,510100
-510131,蒲江县,4,510100
-510181,都江堰市,4,510100
-510182,彭州市,4,510100
-510183,邛崃市,4,510100
-510184,崇州市,4,510100
-510185,简阳市,4,510100
-510302,自流井区,4,510300
-510303,贡井区,4,510300
-510304,大安区,4,510300
-510311,沿滩区,4,510300
-510321,荣县,4,510300
-510322,富顺县,4,510300
-510402,东区,4,510400
-510403,西区,4,510400
-510411,仁和区,4,510400
-510421,米易县,4,510400
-510422,盐边县,4,510400
-510502,江阳区,4,510500
-510503,纳溪区,4,510500
-510504,龙马潭区,4,510500
-510521,泸县,4,510500
-510522,合江县,4,510500
-510524,叙永县,4,510500
-510525,古蔺县,4,510500
-510603,旌阳区,4,510600
-510604,罗江区,4,510600
-510623,中江县,4,510600
-510681,广汉市,4,510600
-510682,什邡市,4,510600
-510683,绵竹市,4,510600
-510703,涪城区,4,510700
-510704,游仙区,4,510700
-510705,安州区,4,510700
-510722,三台县,4,510700
-510723,盐亭县,4,510700
-510725,梓潼县,4,510700
-510726,北川羌族自治县,4,510700
-510727,平武县,4,510700
-510781,江油市,4,510700
-510802,利州区,4,510800
-510811,昭化区,4,510800
-510812,朝天区,4,510800
-510821,旺苍县,4,510800
-510822,青川县,4,510800
-510823,剑阁县,4,510800
-510824,苍溪县,4,510800
-510903,船山区,4,510900
-510904,安居区,4,510900
-510921,蓬溪县,4,510900
-510923,大英县,4,510900
-510981,射洪市,4,510900
-511002,市中区,4,511000
-511011,东兴区,4,511000
-511024,威远县,4,511000
-511025,资中县,4,511000
-511071,内江经济开发区,4,511000
-511083,隆昌市,4,511000
-511102,市中区,4,511100
-511111,沙湾区,4,511100
-511112,五通桥区,4,511100
-511113,金口河区,4,511100
-511123,犍为县,4,511100
-511124,井研县,4,511100
-511126,夹江县,4,511100
-511129,沐川县,4,511100
-511132,峨边彝族自治县,4,511100
-511133,马边彝族自治县,4,511100
-511181,峨眉山市,4,511100
-511302,顺庆区,4,511300
-511303,高坪区,4,511300
-511304,嘉陵区,4,511300
-511321,南部县,4,511300
-511322,营山县,4,511300
-511323,蓬安县,4,511300
-511324,仪陇县,4,511300
-511325,西充县,4,511300
-511381,阆中市,4,511300
-511402,东坡区,4,511400
-511403,彭山区,4,511400
-511421,仁寿县,4,511400
-511423,洪雅县,4,511400
-511424,丹棱县,4,511400
-511425,青神县,4,511400
-511502,翠屏区,4,511500
-511503,南溪区,4,511500
-511504,叙州区,4,511500
-511523,江安县,4,511500
-511524,长宁县,4,511500
-511525,高县,4,511500
-511526,珙县,4,511500
-511527,筠连县,4,511500
-511528,兴文县,4,511500
-511529,屏山县,4,511500
-511602,广安区,4,511600
-511603,前锋区,4,511600
-511621,岳池县,4,511600
-511622,武胜县,4,511600
-511623,邻水县,4,511600
-511681,华蓥市,4,511600
-511702,通川区,4,511700
-511703,达川区,4,511700
-511722,宣汉县,4,511700
-511723,开江县,4,511700
-511724,大竹县,4,511700
-511725,渠县,4,511700
-511771,达州经济开发区,4,511700
-511781,万源市,4,511700
-511802,雨城区,4,511800
-511803,名山区,4,511800
-511822,荥经县,4,511800
-511823,汉源县,4,511800
-511824,石棉县,4,511800
-511825,天全县,4,511800
-511826,芦山县,4,511800
-511827,宝兴县,4,511800
-511902,巴州区,4,511900
-511903,恩阳区,4,511900
-511921,通江县,4,511900
-511922,南江县,4,511900
-511923,平昌县,4,511900
-511971,巴中经济开发区,4,511900
-512002,雁江区,4,512000
-512021,安岳县,4,512000
-512022,乐至县,4,512000
-513201,马尔康市,4,513200
-513221,汶川县,4,513200
-513222,理县,4,513200
-513223,茂县,4,513200
-513224,松潘县,4,513200
-513225,九寨沟县,4,513200
-513226,金川县,4,513200
-513227,小金县,4,513200
-513228,黑水县,4,513200
-513230,壤塘县,4,513200
-513231,阿坝县,4,513200
-513232,若尔盖县,4,513200
-513233,红原县,4,513200
-513301,康定市,4,513300
-513322,泸定县,4,513300
-513323,丹巴县,4,513300
-513324,九龙县,4,513300
-513325,雅江县,4,513300
-513326,道孚县,4,513300
-513327,炉霍县,4,513300
-513328,甘孜县,4,513300
-513329,新龙县,4,513300
-513330,德格县,4,513300
-513331,白玉县,4,513300
-513332,石渠县,4,513300
-513333,色达县,4,513300
-513334,理塘县,4,513300
-513335,巴塘县,4,513300
-513336,乡城县,4,513300
-513337,稻城县,4,513300
-513338,得荣县,4,513300
-513401,西昌市,4,513400
-513402,会理市,4,513400
-513422,木里藏族自治县,4,513400
-513423,盐源县,4,513400
-513424,德昌县,4,513400
-513426,会东县,4,513400
-513427,宁南县,4,513400
-513428,普格县,4,513400
-513429,布拖县,4,513400
-513430,金阳县,4,513400
-513431,昭觉县,4,513400
-513432,喜德县,4,513400
-513433,冕宁县,4,513400
-513434,越西县,4,513400
-513435,甘洛县,4,513400
-513436,美姑县,4,513400
-513437,雷波县,4,513400
-520102,南明区,4,520100
-520103,云岩区,4,520100
-520111,花溪区,4,520100
-520112,乌当区,4,520100
-520113,白云区,4,520100
-520115,观山湖区,4,520100
-520121,开阳县,4,520100
-520122,息烽县,4,520100
-520123,修文县,4,520100
-520181,清镇市,4,520100
-520201,钟山区,4,520200
-520203,六枝特区,4,520200
-520204,水城区,4,520200
-520281,盘州市,4,520200
-520302,红花岗区,4,520300
-520303,汇川区,4,520300
-520304,播州区,4,520300
-520322,桐梓县,4,520300
-520323,绥阳县,4,520300
-520324,正安县,4,520300
-520325,道真仡佬族苗族自治县,4,520300
-520326,务川仡佬族苗族自治县,4,520300
-520327,凤冈县,4,520300
-520328,湄潭县,4,520300
-520329,余庆县,4,520300
-520330,习水县,4,520300
-520381,赤水市,4,520300
-520382,仁怀市,4,520300
-520402,西秀区,4,520400
-520403,平坝区,4,520400
-520422,普定县,4,520400
-520423,镇宁布依族苗族自治县,4,520400
-520424,关岭布依族苗族自治县,4,520400
-520425,紫云苗族布依族自治县,4,520400
-520502,七星关区,4,520500
-520521,大方县,4,520500
-520523,金沙县,4,520500
-520524,织金县,4,520500
-520525,纳雍县,4,520500
-520526,威宁彝族回族苗族自治县,4,520500
-520527,赫章县,4,520500
-520581,黔西市,4,520500
-520602,碧江区,4,520600
-520603,万山区,4,520600
-520621,江口县,4,520600
-520622,玉屏侗族自治县,4,520600
-520623,石阡县,4,520600
-520624,思南县,4,520600
-520625,印江土家族苗族自治县,4,520600
-520626,德江县,4,520600
-520627,沿河土家族自治县,4,520600
-520628,松桃苗族自治县,4,520600
-522301,兴义市,4,522300
-522302,兴仁市,4,522300
-522323,普安县,4,522300
-522324,晴隆县,4,522300
-522325,贞丰县,4,522300
-522326,望谟县,4,522300
-522327,册亨县,4,522300
-522328,安龙县,4,522300
-522601,凯里市,4,522600
-522622,黄平县,4,522600
-522623,施秉县,4,522600
-522624,三穗县,4,522600
-522625,镇远县,4,522600
-522626,岑巩县,4,522600
-522627,天柱县,4,522600
-522628,锦屏县,4,522600
-522629,剑河县,4,522600
-522630,台江县,4,522600
-522631,黎平县,4,522600
-522632,榕江县,4,522600
-522633,从江县,4,522600
-522634,雷山县,4,522600
-522635,麻江县,4,522600
-522636,丹寨县,4,522600
-522701,都匀市,4,522700
-522702,福泉市,4,522700
-522722,荔波县,4,522700
-522723,贵定县,4,522700
-522725,瓮安县,4,522700
-522726,独山县,4,522700
-522727,平塘县,4,522700
-522728,罗甸县,4,522700
-522729,长顺县,4,522700
-522730,龙里县,4,522700
-522731,惠水县,4,522700
-522732,三都水族自治县,4,522700
-530102,五华区,4,530100
-530103,盘龙区,4,530100
-530111,官渡区,4,530100
-530112,西山区,4,530100
-530113,东川区,4,530100
-530114,呈贡区,4,530100
-530115,晋宁区,4,530100
-530124,富民县,4,530100
-530125,宜良县,4,530100
-530126,石林彝族自治县,4,530100
-530127,嵩明县,4,530100
-530128,禄劝彝族苗族自治县,4,530100
-530129,寻甸回族彝族自治县,4,530100
-530181,安宁市,4,530100
-530302,麒麟区,4,530300
-530303,沾益区,4,530300
-530304,马龙区,4,530300
-530322,陆良县,4,530300
-530323,师宗县,4,530300
-530324,罗平县,4,530300
-530325,富源县,4,530300
-530326,会泽县,4,530300
-530381,宣威市,4,530300
-530402,红塔区,4,530400
-530403,江川区,4,530400
-530423,通海县,4,530400
-530424,华宁县,4,530400
-530425,易门县,4,530400
-530426,峨山彝族自治县,4,530400
-530427,新平彝族傣族自治县,4,530400
-530428,元江哈尼族彝族傣族自治县,4,530400
-530481,澄江市,4,530400
-530502,隆阳区,4,530500
-530521,施甸县,4,530500
-530523,龙陵县,4,530500
-530524,昌宁县,4,530500
-530581,腾冲市,4,530500
-530602,昭阳区,4,530600
-530621,鲁甸县,4,530600
-530622,巧家县,4,530600
-530623,盐津县,4,530600
-530624,大关县,4,530600
-530625,永善县,4,530600
-530626,绥江县,4,530600
-530627,镇雄县,4,530600
-530628,彝良县,4,530600
-530629,威信县,4,530600
-530681,水富市,4,530600
-530702,古城区,4,530700
-530721,玉龙纳西族自治县,4,530700
-530722,永胜县,4,530700
-530723,华坪县,4,530700
-530724,宁蒗彝族自治县,4,530700
-530802,思茅区,4,530800
-530821,宁洱哈尼族彝族自治县,4,530800
-530822,墨江哈尼族自治县,4,530800
-530823,景东彝族自治县,4,530800
-530824,景谷傣族彝族自治县,4,530800
-530825,镇沅彝族哈尼族拉祜族自治县,4,530800
-530826,江城哈尼族彝族自治县,4,530800
-530827,孟连傣族拉祜族佤族自治县,4,530800
-530828,澜沧拉祜族自治县,4,530800
-530829,西盟佤族自治县,4,530800
-530902,临翔区,4,530900
-530921,凤庆县,4,530900
-530922,云县,4,530900
-530923,永德县,4,530900
-530924,镇康县,4,530900
-530925,双江拉祜族佤族布朗族傣族自治县,4,530900
-530926,耿马傣族佤族自治县,4,530900
-530927,沧源佤族自治县,4,530900
-532301,楚雄市,4,532300
-532302,禄丰市,4,532300
-532322,双柏县,4,532300
-532323,牟定县,4,532300
-532324,南华县,4,532300
-532325,姚安县,4,532300
-532326,大姚县,4,532300
-532327,永仁县,4,532300
-532328,元谋县,4,532300
-532329,武定县,4,532300
-532501,个旧市,4,532500
-532502,开远市,4,532500
-532503,蒙自市,4,532500
-532504,弥勒市,4,532500
-532523,屏边苗族自治县,4,532500
-532524,建水县,4,532500
-532525,石屏县,4,532500
-532527,泸西县,4,532500
-532528,元阳县,4,532500
-532529,红河县,4,532500
-532530,金平苗族瑶族傣族自治县,4,532500
-532531,绿春县,4,532500
-532532,河口瑶族自治县,4,532500
-532601,文山市,4,532600
-532622,砚山县,4,532600
-532623,西畴县,4,532600
-532624,麻栗坡县,4,532600
-532625,马关县,4,532600
-532626,丘北县,4,532600
-532627,广南县,4,532600
-532628,富宁县,4,532600
-532801,景洪市,4,532800
-532822,勐海县,4,532800
-532823,勐腊县,4,532800
-532901,大理市,4,532900
-532922,漾濞彝族自治县,4,532900
-532923,祥云县,4,532900
-532924,宾川县,4,532900
-532925,弥渡县,4,532900
-532926,南涧彝族自治县,4,532900
-532927,巍山彝族回族自治县,4,532900
-532928,永平县,4,532900
-532929,云龙县,4,532900
-532930,洱源县,4,532900
-532931,剑川县,4,532900
-532932,鹤庆县,4,532900
-533102,瑞丽市,4,533100
-533103,芒市,4,533100
-533122,梁河县,4,533100
-533123,盈江县,4,533100
-533124,陇川县,4,533100
-533301,泸水市,4,533300
-533323,福贡县,4,533300
-533324,贡山独龙族怒族自治县,4,533300
-533325,兰坪白族普米族自治县,4,533300
-533401,香格里拉市,4,533400
-533422,德钦县,4,533400
-533423,维西傈僳族自治县,4,533400
-540102,城关区,4,540100
-540103,堆龙德庆区,4,540100
-540104,达孜区,4,540100
-540121,林周县,4,540100
-540122,当雄县,4,540100
-540123,尼木县,4,540100
-540124,曲水县,4,540100
-540127,墨竹工卡县,4,540100
-540171,格尔木藏青工业园区,4,540100
-540172,拉萨经济技术开发区,4,540100
-540173,西藏文化旅游创意园区,4,540100
-540174,达孜工业园区,4,540100
-540202,桑珠孜区,4,540200
-540221,南木林县,4,540200
-540222,江孜县,4,540200
-540223,定日县,4,540200
-540224,萨迦县,4,540200
-540225,拉孜县,4,540200
-540226,昂仁县,4,540200
-540227,谢通门县,4,540200
-540228,白朗县,4,540200
-540229,仁布县,4,540200
-540230,康马县,4,540200
-540231,定结县,4,540200
-540232,仲巴县,4,540200
-540233,亚东县,4,540200
-540234,吉隆县,4,540200
-540235,聂拉木县,4,540200
-540236,萨嘎县,4,540200
-540237,岗巴县,4,540200
-540302,卡若区,4,540300
-540321,江达县,4,540300
-540322,贡觉县,4,540300
-540323,类乌齐县,4,540300
-540324,丁青县,4,540300
-540325,察雅县,4,540300
-540326,八宿县,4,540300
-540327,左贡县,4,540300
-540328,芒康县,4,540300
-540329,洛隆县,4,540300
-540330,边坝县,4,540300
-540402,巴宜区,4,540400
-540421,工布江达县,4,540400
-540422,米林县,4,540400
-540423,墨脱县,4,540400
-540424,波密县,4,540400
-540425,察隅县,4,540400
-540426,朗县,4,540400
-540502,乃东区,4,540500
-540521,扎囊县,4,540500
-540522,贡嘎县,4,540500
-540523,桑日县,4,540500
-540524,琼结县,4,540500
-540525,曲松县,4,540500
-540526,措美县,4,540500
-540527,洛扎县,4,540500
-540528,加查县,4,540500
-540529,隆子县,4,540500
-540530,错那县,4,540500
-540531,浪卡子县,4,540500
-540602,色尼区,4,540600
-540621,嘉黎县,4,540600
-540622,比如县,4,540600
-540623,聂荣县,4,540600
-540624,安多县,4,540600
-540625,申扎县,4,540600
-540626,索县,4,540600
-540627,班戈县,4,540600
-540628,巴青县,4,540600
-540629,尼玛县,4,540600
-540630,双湖县,4,540600
-542521,普兰县,4,542500
-542522,札达县,4,542500
-542523,噶尔县,4,542500
-542524,日土县,4,542500
-542525,革吉县,4,542500
-542526,改则县,4,542500
-542527,措勤县,4,542500
-610102,新城区,4,610100
-610103,碑林区,4,610100
-610104,莲湖区,4,610100
-610111,灞桥区,4,610100
-610112,未央区,4,610100
-610113,雁塔区,4,610100
-610114,阎良区,4,610100
-610115,临潼区,4,610100
-610116,长安区,4,610100
-610117,高陵区,4,610100
-610118,鄠邑区,4,610100
-610122,蓝田县,4,610100
-610124,周至县,4,610100
-610202,王益区,4,610200
-610203,印台区,4,610200
-610204,耀州区,4,610200
-610222,宜君县,4,610200
-610302,渭滨区,4,610300
-610303,金台区,4,610300
-610304,陈仓区,4,610300
-610305,凤翔区,4,610300
-610323,岐山县,4,610300
-610324,扶风县,4,610300
-610326,眉县,4,610300
-610327,陇县,4,610300
-610328,千阳县,4,610300
-610329,麟游县,4,610300
-610330,凤县,4,610300
-610331,太白县,4,610300
-610402,秦都区,4,610400
-610403,杨陵区,4,610400
-610404,渭城区,4,610400
-610422,三原县,4,610400
-610423,泾阳县,4,610400
-610424,乾县,4,610400
-610425,礼泉县,4,610400
-610426,永寿县,4,610400
-610428,长武县,4,610400
-610429,旬邑县,4,610400
-610430,淳化县,4,610400
-610431,武功县,4,610400
-610481,兴平市,4,610400
-610482,彬州市,4,610400
-610502,临渭区,4,610500
-610503,华州区,4,610500
-610522,潼关县,4,610500
-610523,大荔县,4,610500
-610524,合阳县,4,610500
-610525,澄城县,4,610500
-610526,蒲城县,4,610500
-610527,白水县,4,610500
-610528,富平县,4,610500
-610581,韩城市,4,610500
-610582,华阴市,4,610500
-610602,宝塔区,4,610600
-610603,安塞区,4,610600
-610621,延长县,4,610600
-610622,延川县,4,610600
-610625,志丹县,4,610600
-610626,吴起县,4,610600
-610627,甘泉县,4,610600
-610628,富县,4,610600
-610629,洛川县,4,610600
-610630,宜川县,4,610600
-610631,黄龙县,4,610600
-610632,黄陵县,4,610600
-610681,子长市,4,610600
-610702,汉台区,4,610700
-610703,南郑区,4,610700
-610722,城固县,4,610700
-610723,洋县,4,610700
-610724,西乡县,4,610700
-610725,勉县,4,610700
-610726,宁强县,4,610700
-610727,略阳县,4,610700
-610728,镇巴县,4,610700
-610729,留坝县,4,610700
-610730,佛坪县,4,610700
-610802,榆阳区,4,610800
-610803,横山区,4,610800
-610822,府谷县,4,610800
-610824,靖边县,4,610800
-610825,定边县,4,610800
-610826,绥德县,4,610800
-610827,米脂县,4,610800
-610828,佳县,4,610800
-610829,吴堡县,4,610800
-610830,清涧县,4,610800
-610831,子洲县,4,610800
-610881,神木市,4,610800
-610902,汉滨区,4,610900
-610921,汉阴县,4,610900
-610922,石泉县,4,610900
-610923,宁陕县,4,610900
-610924,紫阳县,4,610900
-610925,岚皋县,4,610900
-610926,平利县,4,610900
-610927,镇坪县,4,610900
-610929,白河县,4,610900
-610981,旬阳市,4,610900
-611002,商州区,4,611000
-611021,洛南县,4,611000
-611022,丹凤县,4,611000
-611023,商南县,4,611000
-611024,山阳县,4,611000
-611025,镇安县,4,611000
-611026,柞水县,4,611000
-620102,城关区,4,620100
-620103,七里河区,4,620100
-620104,西固区,4,620100
-620105,安宁区,4,620100
-620111,红古区,4,620100
-620121,永登县,4,620100
-620122,皋兰县,4,620100
-620123,榆中县,4,620100
-620171,兰州新区,4,620100
-620201,嘉峪关市,4,620200
-620302,金川区,4,620300
-620321,永昌县,4,620300
-620402,白银区,4,620400
-620403,平川区,4,620400
-620421,靖远县,4,620400
-620422,会宁县,4,620400
-620423,景泰县,4,620400
-620502,秦州区,4,620500
-620503,麦积区,4,620500
-620521,清水县,4,620500
-620522,秦安县,4,620500
-620523,甘谷县,4,620500
-620524,武山县,4,620500
-620525,张家川回族自治县,4,620500
-620602,凉州区,4,620600
-620621,民勤县,4,620600
-620622,古浪县,4,620600
-620623,天祝藏族自治县,4,620600
-620702,甘州区,4,620700
-620721,肃南裕固族自治县,4,620700
-620722,民乐县,4,620700
-620723,临泽县,4,620700
-620724,高台县,4,620700
-620725,山丹县,4,620700
-620802,崆峒区,4,620800
-620821,泾川县,4,620800
-620822,灵台县,4,620800
-620823,崇信县,4,620800
-620825,庄浪县,4,620800
-620826,静宁县,4,620800
-620881,华亭市,4,620800
-620902,肃州区,4,620900
-620921,金塔县,4,620900
-620922,瓜州县,4,620900
-620923,肃北蒙古族自治县,4,620900
-620924,阿克塞哈萨克族自治县,4,620900
-620981,玉门市,4,620900
-620982,敦煌市,4,620900
-621002,西峰区,4,621000
-621021,庆城县,4,621000
-621022,环县,4,621000
-621023,华池县,4,621000
-621024,合水县,4,621000
-621025,正宁县,4,621000
-621026,宁县,4,621000
-621027,镇原县,4,621000
-621102,安定区,4,621100
-621121,通渭县,4,621100
-621122,陇西县,4,621100
-621123,渭源县,4,621100
-621124,临洮县,4,621100
-621125,漳县,4,621100
-621126,岷县,4,621100
-621202,武都区,4,621200
-621221,成县,4,621200
-621222,文县,4,621200
-621223,宕昌县,4,621200
-621224,康县,4,621200
-621225,西和县,4,621200
-621226,礼县,4,621200
-621227,徽县,4,621200
-621228,两当县,4,621200
-622901,临夏市,4,622900
-622921,临夏县,4,622900
-622922,康乐县,4,622900
-622923,永靖县,4,622900
-622924,广河县,4,622900
-622925,和政县,4,622900
-622926,东乡族自治县,4,622900
-622927,积石山保安族东乡族撒拉族自治县,4,622900
-623001,合作市,4,623000
-623021,临潭县,4,623000
-623022,卓尼县,4,623000
-623023,舟曲县,4,623000
-623024,迭部县,4,623000
-623025,玛曲县,4,623000
-623026,碌曲县,4,623000
-623027,夏河县,4,623000
-630102,城东区,4,630100
-630103,城中区,4,630100
-630104,城西区,4,630100
-630105,城北区,4,630100
-630106,湟中区,4,630100
-630121,大通回族土族自治县,4,630100
-630123,湟源县,4,630100
-630202,乐都区,4,630200
-630203,平安区,4,630200
-630222,民和回族土族自治县,4,630200
-630223,互助土族自治县,4,630200
-630224,化隆回族自治县,4,630200
-630225,循化撒拉族自治县,4,630200
-632221,门源回族自治县,4,632200
-632222,祁连县,4,632200
-632223,海晏县,4,632200
-632224,刚察县,4,632200
-632301,同仁市,4,632300
-632322,尖扎县,4,632300
-632323,泽库县,4,632300
-632324,河南蒙古族自治县,4,632300
-632521,共和县,4,632500
-632522,同德县,4,632500
-632523,贵德县,4,632500
-632524,兴海县,4,632500
-632525,贵南县,4,632500
-632621,玛沁县,4,632600
-632622,班玛县,4,632600
-632623,甘德县,4,632600
-632624,达日县,4,632600
-632625,久治县,4,632600
-632626,玛多县,4,632600
-632701,玉树市,4,632700
-632722,杂多县,4,632700
-632723,称多县,4,632700
-632724,治多县,4,632700
-632725,囊谦县,4,632700
-632726,曲麻莱县,4,632700
-632801,格尔木市,4,632800
-632802,德令哈市,4,632800
-632803,茫崖市,4,632800
-632821,乌兰县,4,632800
-632822,都兰县,4,632800
-632823,天峻县,4,632800
-632857,大柴旦行政委员会,4,632800
-640104,兴庆区,4,640100
-640105,西夏区,4,640100
-640106,金凤区,4,640100
-640121,永宁县,4,640100
-640122,贺兰县,4,640100
-640181,灵武市,4,640100
-640202,大武口区,4,640200
-640205,惠农区,4,640200
-640221,平罗县,4,640200
-640302,利通区,4,640300
-640303,红寺堡区,4,640300
-640323,盐池县,4,640300
-640324,同心县,4,640300
-640381,青铜峡市,4,640300
-640402,原州区,4,640400
-640422,西吉县,4,640400
-640423,隆德县,4,640400
-640424,泾源县,4,640400
-640425,彭阳县,4,640400
-640502,沙坡头区,4,640500
-640521,中宁县,4,640500
-640522,海原县,4,640500
-650102,天山区,4,650100
-650103,沙依巴克区,4,650100
-650104,新市区,4,650100
-650105,水磨沟区,4,650100
-650106,头屯河区,4,650100
-650107,达坂城区,4,650100
-650109,米东区,4,650100
-650121,乌鲁木齐县,4,650100
-650202,独山子区,4,650200
-650203,克拉玛依区,4,650200
-650204,白碱滩区,4,650200
-650205,乌尔禾区,4,650200
-650402,高昌区,4,650400
-650421,鄯善县,4,650400
-650422,托克逊县,4,650400
-650502,伊州区,4,650500
-650521,巴里坤哈萨克自治县,4,650500
-650522,伊吾县,4,650500
-652301,昌吉市,4,652300
-652302,阜康市,4,652300
-652323,呼图壁县,4,652300
-652324,玛纳斯县,4,652300
-652325,奇台县,4,652300
-652327,吉木萨尔县,4,652300
-652328,木垒哈萨克自治县,4,652300
-652701,博乐市,4,652700
-652702,阿拉山口市,4,652700
-652722,精河县,4,652700
-652723,温泉县,4,652700
-652801,库尔勒市,4,652800
-652822,轮台县,4,652800
-652823,尉犁县,4,652800
-652824,若羌县,4,652800
-652825,且末县,4,652800
-652826,焉耆回族自治县,4,652800
-652827,和静县,4,652800
-652828,和硕县,4,652800
-652829,博湖县,4,652800
-652871,库尔勒经济技术开发区,4,652800
-652901,阿克苏市,4,652900
-652902,库车市,4,652900
-652922,温宿县,4,652900
-652924,沙雅县,4,652900
-652925,新和县,4,652900
-652926,拜城县,4,652900
-652927,乌什县,4,652900
-652928,阿瓦提县,4,652900
-652929,柯坪县,4,652900
-653001,阿图什市,4,653000
-653022,阿克陶县,4,653000
-653023,阿合奇县,4,653000
-653024,乌恰县,4,653000
-653101,喀什市,4,653100
-653121,疏附县,4,653100
-653122,疏勒县,4,653100
-653123,英吉沙县,4,653100
-653124,泽普县,4,653100
-653125,莎车县,4,653100
-653126,叶城县,4,653100
-653127,麦盖提县,4,653100
-653128,岳普湖县,4,653100
-653129,伽师县,4,653100
-653130,巴楚县,4,653100
-653131,塔什库尔干塔吉克自治县,4,653100
-653201,和田市,4,653200
-653221,和田县,4,653200
-653222,墨玉县,4,653200
-653223,皮山县,4,653200
-653224,洛浦县,4,653200
-653225,策勒县,4,653200
-653226,于田县,4,653200
-653227,民丰县,4,653200
-654002,伊宁市,4,654000
-654003,奎屯市,4,654000
-654004,霍尔果斯市,4,654000
-654021,伊宁县,4,654000
-654022,察布查尔锡伯自治县,4,654000
-654023,霍城县,4,654000
-654024,巩留县,4,654000
-654025,新源县,4,654000
-654026,昭苏县,4,654000
-654027,特克斯县,4,654000
-654028,尼勒克县,4,654000
-654201,塔城市,4,654200
-654202,乌苏市,4,654200
-654203,沙湾市,4,654200
-654221,额敏县,4,654200
-654224,托里县,4,654200
-654225,裕民县,4,654200
-654226,和布克赛尔蒙古自治县,4,654200
-654301,阿勒泰市,4,654300
-654321,布尔津县,4,654300
-654322,富蕴县,4,654300
-654323,福海县,4,654300
-654324,哈巴河县,4,654300
-654325,青河县,4,654300
-654326,吉木乃县,4,654300
-659001,石河子市,4,659000
-659002,阿拉尔市,4,659000
-659003,图木舒克市,4,659000
-659004,五家渠市,4,659000
-659005,北屯市,4,659000
-659006,铁门关市,4,659000
-659007,双河市,4,659000
-659008,可克达拉市,4,659000
-659009,昆玉市,4,659000
-659010,胡杨河市,4,659000
-659011,新星市,4,659000
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-biz-ip/src/main/resources/ip2region.xdb b/iailab-framework/iailab-common-biz-ip/src/main/resources/ip2region.xdb
deleted file mode 100644
index 58596a5..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/main/resources/ip2region.xdb
+++ /dev/null
Binary files differ
diff --git a/iailab-framework/iailab-common-biz-ip/src/test/java/com/iailab/framework/ip/core/utils/AreaUtilsTest.java b/iailab-framework/iailab-common-biz-ip/src/test/java/com/iailab/framework/ip/core/utils/AreaUtilsTest.java
deleted file mode 100644
index 67d12d5..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/test/java/com/iailab/framework/ip/core/utils/AreaUtilsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.ip.core.utils;
-
-
-import com.iailab.framework.ip.core.Area;
-import com.iailab.framework.ip.core.enums.AreaTypeEnum;
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * {@link AreaUtils} 的单元测试
- *
- * @author iailab
- */
-public class AreaUtilsTest {
-
-    @Test
-    public void testGetArea() {
-        // 调用:北京
-        Area area = AreaUtils.getArea(110100);
-        // 断言
-        assertEquals(area.getId(), 110100);
-        assertEquals(area.getName(), "北京市");
-        assertEquals(area.getType(), AreaTypeEnum.CITY.getType());
-        assertEquals(area.getParent().getId(), 110000);
-        assertEquals(area.getChildren().size(), 16);
-    }
-
-    @Test
-    public void testFormat() {
-        assertEquals(AreaUtils.format(110105), "北京 北京市 朝阳区");
-        assertEquals(AreaUtils.format(1), "中国");
-        assertEquals(AreaUtils.format(2), "蒙古");
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-ip/src/test/java/com/iailab/framework/ip/core/utils/IPUtilsTest.java b/iailab-framework/iailab-common-biz-ip/src/test/java/com/iailab/framework/ip/core/utils/IPUtilsTest.java
deleted file mode 100644
index 4d4e3b8..0000000
--- a/iailab-framework/iailab-common-biz-ip/src/test/java/com/iailab/framework/ip/core/utils/IPUtilsTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.iailab.framework.ip.core.utils;
-
-import com.iailab.framework.ip.core.Area;
-import org.junit.jupiter.api.Test;
-import org.lionsoul.ip2region.xdb.Searcher;
-
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * {@link IPUtils} 的单元测试
- *
- * @author wanglhup
- */
-public class IPUtilsTest {
-
-    @Test
-    public void testGetAreaId_string() {
-        // 120.202.4.0|120.202.4.255|420600
-        Integer areaId = IPUtils.getAreaId("120.202.4.50");
-        assertEquals(420600, areaId);
-    }
-
-    @Test
-    public void testGetAreaId_long() throws Exception {
-        // 120.203.123.0|120.203.133.255|360900
-        long ip = Searcher.checkIP("120.203.123.250");
-        Integer areaId = IPUtils.getAreaId(ip);
-        assertEquals(360900, areaId);
-    }
-
-    @Test
-    public void testGetArea_string() {
-        // 120.202.4.0|120.202.4.255|420600
-        Area area = IPUtils.getArea("120.202.4.50");
-        assertEquals("襄阳市", area.getName());
-    }
-
-    @Test
-    public void testGetArea_long() throws Exception {
-        // 120.203.123.0|120.203.133.255|360900
-        long ip = Searcher.checkIP("120.203.123.252");
-        Area area = IPUtils.getArea(ip);
-        assertEquals("宜春市", area.getName());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/pom.xml b/iailab-framework/iailab-common-biz-tenant/pom.xml
deleted file mode 100644
index 3c4431e..0000000
--- a/iailab-framework/iailab-common-biz-tenant/pom.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>iailab-framework</artifactId>
-        <groupId>com.iailab</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-biz-tenant</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>多租户</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-security</artifactId>
-        </dependency>
-
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-mybatis</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-redis</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-        </dependency>
-
-        <!-- RPC 远程调用相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-rpc</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Job 定时任务相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-job</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- 消息队列相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-mq</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.kafka</groupId>
-            <artifactId>spring-kafka</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.amqp</groupId>
-            <artifactId>spring-rabbit</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.rocketmq</groupId>
-            <artifactId>rocketmq-spring-boot-starter</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/IailabTenantAutoConfiguration.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/IailabTenantAutoConfiguration.java
deleted file mode 100644
index 14060f8..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/IailabTenantAutoConfiguration.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.iailab.framework.tenant.config;
-
-import com.baomidou.dynamic.datasource.processor.DsProcessor;
-import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor;
-import com.iailab.framework.common.enums.WebFilterOrderEnum;
-import com.iailab.framework.mybatis.core.util.MyBatisUtils;
-import com.iailab.framework.redis.config.IailabCacheProperties;
-import com.iailab.framework.tenant.core.aop.TenantIgnoreAspect;
-import com.iailab.framework.tenant.core.db.TenantDatabaseInterceptor;
-import com.iailab.framework.tenant.core.db.dynamic.TenantDsProcessor;
-import com.iailab.framework.tenant.core.job.TenantJobAspect;
-import com.iailab.framework.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
-import com.iailab.framework.tenant.core.mq.redis.TenantRedisMessageInterceptor;
-import com.iailab.framework.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
-import com.iailab.framework.tenant.core.redis.TenantRedisCacheManager;
-import com.iailab.framework.tenant.core.security.TenantSecurityWebFilter;
-import com.iailab.framework.tenant.core.service.TenantFrameworkService;
-import com.iailab.framework.tenant.core.service.TenantFrameworkServiceImpl;
-import com.iailab.framework.tenant.core.web.TenantContextWebFilter;
-import com.iailab.framework.web.config.WebProperties;
-import com.iailab.framework.web.core.handler.GlobalExceptionHandler;
-import com.iailab.module.system.api.tenant.TenantApi;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Primary;
-import org.springframework.data.redis.cache.BatchStrategies;
-import org.springframework.data.redis.cache.RedisCacheConfiguration;
-import org.springframework.data.redis.cache.RedisCacheManager;
-import org.springframework.data.redis.cache.RedisCacheWriter;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.data.redis.core.RedisTemplate;
-
-import java.util.Objects;
-
-@AutoConfiguration
-@ConditionalOnProperty(prefix = "iailab.tenant", value = "enable", matchIfMissing = true) // 允许使用 iailab.tenant.enable=false 禁用多租户
-@EnableConfigurationProperties(TenantProperties.class)
-public class IailabTenantAutoConfiguration {
-
-    @Bean
-    public TenantFrameworkService tenantFrameworkService(TenantApi tenantApi) {
-        return new TenantFrameworkServiceImpl(tenantApi);
-    }
-
-    // ========== AOP ==========
-
-    @Bean
-    public TenantIgnoreAspect tenantIgnoreAspect() {
-        return new TenantIgnoreAspect();
-    }
-
-    // ========== DB ==========
-
-    @Bean
-    public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
-                                                                 MybatisPlusInterceptor interceptor) {
-        TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
-        // 添加到 interceptor 中
-        // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
-        MyBatisUtils.addInterceptor(interceptor, inner, 0);
-        return inner;
-    }
-
-    @Bean
-    public DsProcessor dsProcessor(
-//            TenantFrameworkService tenantFrameworkService,
-//                                   DataSource dataSource,
-//                                   DefaultDataSourceCreator dataSourceCreator
-    ) {
-//        TenantDsProcessor tenantDsProcessor = new TenantDsProcessor(tenantFrameworkService, dataSourceCreator);
-        TenantDsProcessor tenantDsProcessor = new TenantDsProcessor();
-        tenantDsProcessor.setNextProcessor(new DsSpelExpressionProcessor());
-        return tenantDsProcessor;
-    }
-
-    // ========== WEB ==========
-
-    @Bean
-    public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
-        FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
-        registrationBean.setFilter(new TenantContextWebFilter());
-        registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
-        return registrationBean;
-    }
-
-    // ========== Security ==========
-
-    @Bean
-    public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties,
-                                                                                   WebProperties webProperties,
-                                                                                   GlobalExceptionHandler globalExceptionHandler,
-                                                                                   TenantFrameworkService tenantFrameworkService) {
-        FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
-        registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
-                globalExceptionHandler, tenantFrameworkService));
-        registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
-        return registrationBean;
-    }
-
-    // ========== Job ==========
-
-    @Bean
-    @ConditionalOnClass(name = "com.xxl.job.core.handler.annotation.XxlJob")
-    public TenantJobAspect tenantJobAspect(TenantFrameworkService tenantFrameworkService) {
-        return new TenantJobAspect(tenantFrameworkService);
-    }
-
-    // ========== MQ ==========
-
-    /**
-     * 多租户 Redis 消息队列的配置类
-     *
-     * 为什么要单独一个配置类呢?如果直接把 TenantRedisMessageInterceptor Bean 的初始化放外面,会报 RedisMessageInterceptor 类不存在的错误
-     */
-    @Configuration
-    @ConditionalOnClass(name = "com.iailab.framework.mq.redis.core.RedisMQTemplate")
-    public static class TenantRedisMQAutoConfiguration {
-
-        @Bean
-        public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
-            return new TenantRedisMessageInterceptor();
-        }
-
-    }
-
-    @Bean
-    @ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
-    public TenantRabbitMQInitializer tenantRabbitMQInitializer() {
-        return new TenantRabbitMQInitializer();
-    }
-
-    @Bean
-    @ConditionalOnClass(name = "org.apache.rocketmq.spring.core.RocketMQTemplate")
-    public TenantRocketMQInitializer tenantRocketMQInitializer() {
-        return new TenantRocketMQInitializer();
-    }
-
-    // ========== Redis ==========
-
-    @Bean
-    @Primary // 引入租户时,tenantRedisCacheManager 为主 Bean
-    public RedisCacheManager tenantRedisCacheManager(RedisTemplate<String, Object> redisTemplate,
-                                                     RedisCacheConfiguration redisCacheConfiguration,
-                                                     IailabCacheProperties iailabCacheProperties,
-                                                     TenantProperties tenantProperties) {
-        // 创建 RedisCacheWriter 对象
-        RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory());
-        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory,
-                BatchStrategies.scan(iailabCacheProperties.getRedisScanBatchSize()));
-        // 创建 TenantRedisCacheManager 对象
-        return new TenantRedisCacheManager(cacheWriter, redisCacheConfiguration, tenantProperties.getIgnoreCaches());
-    }
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/IailabTenantRpcAutoConfiguration.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/IailabTenantRpcAutoConfiguration.java
deleted file mode 100644
index cfa5d68..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/IailabTenantRpcAutoConfiguration.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.framework.tenant.config;
-
-import com.iailab.framework.tenant.core.rpc.TenantRequestInterceptor;
-import com.iailab.module.system.api.tenant.TenantApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.cloud.openfeign.EnableFeignClients;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@AutoConfiguration
-@ConditionalOnProperty(prefix = "iailab.tenant", value = "enable", matchIfMissing = true) // 允许使用 iailab.tenant.enable=false 禁用多租户
-@EnableFeignClients(clients = TenantApi.class) // 主要是引入相关的 API 服务
-public class IailabTenantRpcAutoConfiguration {
-
-    @Bean
-    public TenantRequestInterceptor tenantRequestInterceptor() {
-        return new TenantRequestInterceptor();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/TenantProperties.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/TenantProperties.java
deleted file mode 100644
index 4fc2ddf..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/config/TenantProperties.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.iailab.framework.tenant.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * 多租户配置
- *
- * @author iailab
- */
-@ConfigurationProperties(prefix = "iailab.tenant")
-@Data
-public class TenantProperties {
-
-    /**
-     * 租户是否开启
-     */
-    private static final Boolean ENABLE_DEFAULT = true;
-
-    /**
-     * 是否开启
-     */
-    private Boolean enable = ENABLE_DEFAULT;
-
-    /**
-     * 需要忽略多租户的请求
-     *
-     * 默认情况下,每个请求需要带上 tenant-id 的请求头。但是,部分请求是无需带上的,例如说短信回调、支付回调等 Open API!
-     */
-    private Set<String> ignoreUrls = Collections.emptySet();
-
-    /**
-     * 需要忽略多租户的表
-     *
-     * 即默认所有表都开启多租户的功能,所以记得添加对应的 tenant_id 字段哟
-     */
-    private Set<String> ignoreTables = Collections.emptySet();
-
-    /**
-     * 需要忽略多租户的 Spring Cache 缓存
-     *
-     * 即默认所有缓存都开启多租户的功能,所以记得添加对应的 tenant_id 字段哟
-     */
-    private Set<String> ignoreCaches = Collections.emptySet();
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/aop/TenantIgnore.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/aop/TenantIgnore.java
deleted file mode 100644
index adf4915..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/aop/TenantIgnore.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.iailab.framework.tenant.core.aop;
-
-import java.lang.annotation.*;
-
-/**
- * 忽略租户,标记指定方法不进行租户的自动过滤
- *
- * 注意,只有 DB 的场景会过滤,其它场景暂时不过滤:
- * 1、Redis 场景:因为是基于 Key 实现多租户的能力,所以忽略没有意义,不像 DB 是一个 column 实现的
- * 2、MQ 场景:有点难以抉择,目前可以通过 Consumer 手动在消费的方法上,添加 @TenantIgnore 进行忽略
- *
- * @author iailab
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-public @interface TenantIgnore {
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/aop/TenantIgnoreAspect.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/aop/TenantIgnoreAspect.java
deleted file mode 100644
index 4814290..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/aop/TenantIgnoreAspect.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.tenant.core.aop;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.tenant.core.util.TenantUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-
-/**
- * 忽略多租户的 Aspect,基于 {@link TenantIgnore} 注解实现,用于一些全局的逻辑。
- * 例如说,一个定时任务,读取所有数据,进行处理。
- * 又例如说,读取所有数据,进行缓存。
- *
- * 整体逻辑的实现,和 {@link TenantUtils#executeIgnore(Runnable)} 需要保持一致
- *
- * @author iailab
- */
-@Aspect
-@Slf4j
-public class TenantIgnoreAspect {
-
-    @Around("@annotation(tenantIgnore)")
-    public Object around(ProceedingJoinPoint joinPoint, TenantIgnore tenantIgnore) throws Throwable {
-        Boolean oldIgnore = TenantContextHolder.isIgnore();
-        try {
-            TenantContextHolder.setIgnore(true);
-            // 执行逻辑
-            return joinPoint.proceed();
-        } finally {
-            TenantContextHolder.setIgnore(oldIgnore);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/context/DataContextHolder.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/context/DataContextHolder.java
deleted file mode 100644
index 297ed1d..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/context/DataContextHolder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.iailab.framework.tenant.core.context;
-
-import com.alibaba.ttl.TransmittableThreadLocal;
-import com.iailab.framework.common.enums.DocumentEnum;
-
-/**
- * 数据源上下文 Holder
- *
- * @author iailab
- */
-public class DataContextHolder {
-
-    /**
-     * 数据源id
-     */
-    private static final ThreadLocal<Long> DATA_SOURCE_ID =  new TransmittableThreadLocal<>();
-
-    /**
-     * 数据源id
-     *
-     * @return 租户编号
-     */
-    public static Long getDataSourceId() {
-        return DATA_SOURCE_ID.get();
-    }
-
-    /**
-     * 数据源id。如果不存在,则抛出 NullPointerException 异常
-     *
-     * @return 租户编号
-     */
-    public static Long getRequiredDataSourceId() {
-        Long dataSourceId = getDataSourceId();
-        if (dataSourceId == null) {
-            throw new NullPointerException("DataContextHolder 不存在数据源id!可参考文档:"
-                + DocumentEnum.TENANT.getUrl());
-        }
-        return dataSourceId;
-    }
-
-    public static void setDataSourceId(Long dataSourceId) {
-        DATA_SOURCE_ID.set(dataSourceId);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/context/TenantContextHolder.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/context/TenantContextHolder.java
deleted file mode 100644
index 1407a84..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/context/TenantContextHolder.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.iailab.framework.tenant.core.context;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.enums.DocumentEnum;
-import com.alibaba.ttl.TransmittableThreadLocal;
-
-/**
- * 多租户上下文 Holder
- *
- * @author iailab
- */
-public class TenantContextHolder {
-
-    /**
-     * 当前租户编号
-     */
-    private static final ThreadLocal<Long> TENANT_ID = new TransmittableThreadLocal<>();
-
-    /**
-     * 是否忽略租户
-     */
-    private static final ThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>();
-
-    /**
-     * 获得租户编号
-     *
-     * @return 租户编号
-     */
-    public static Long getTenantId() {
-        return TENANT_ID.get();
-    }
-
-    /**
-     * 获得租户编号。如果不存在,则抛出 NullPointerException 异常
-     *
-     * @return 租户编号
-     */
-    public static Long getRequiredTenantId() {
-        Long tenantId = getTenantId();
-        if (tenantId == null) {
-            throw new NullPointerException("TenantContextHolder 不存在租户编号!可参考文档:"
-                + DocumentEnum.TENANT.getUrl());
-        }
-        return tenantId;
-    }
-
-    public static void setTenantId(Long tenantId) {
-        TENANT_ID.set(tenantId);
-    }
-
-    public static void setIgnore(Boolean ignore) {
-        IGNORE.set(ignore);
-    }
-
-    /**
-     * 当前是否忽略租户
-     *
-     * @return 是否忽略
-     */
-    public static boolean isIgnore() {
-        return Boolean.TRUE.equals(IGNORE.get());
-    }
-
-    public static void clear() {
-        TENANT_ID.remove();
-        IGNORE.remove();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/TenantBaseDO.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/TenantBaseDO.java
deleted file mode 100644
index bcfa9a8..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/TenantBaseDO.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.framework.tenant.core.db;
-
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 拓展多租户的 BaseDO 基类
- *
- * @author iailab
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public abstract class TenantBaseDO extends BaseDO {
-
-    /**
-     * 多租户编号
-     */
-    private Long tenantId;
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/TenantDatabaseInterceptor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/TenantDatabaseInterceptor.java
deleted file mode 100644
index d24f92c..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/TenantDatabaseInterceptor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.iailab.framework.tenant.core.db;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.tenant.config.TenantProperties;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.LongValue;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * 基于 MyBatis Plus 多租户的功能,实现 DB 层面的多租户的功能
- *
- * @author iailab
- */
-public class TenantDatabaseInterceptor implements TenantLineHandler {
-
-    private final Set<String> ignoreTables = new HashSet<>();
-
-    public TenantDatabaseInterceptor(TenantProperties properties) {
-        // 不同 DB 下,大小写的习惯不同,所以需要都添加进去
-        properties.getIgnoreTables().forEach(table -> {
-            ignoreTables.add(table.toLowerCase());
-            ignoreTables.add(table.toUpperCase());
-        });
-        // 在 OracleKeyGenerator 中,生成主键时,会查询这个表,查询这个表后,会自动拼接 TENANT_ID 导致报错
-        ignoreTables.add("DUAL");
-    }
-
-    @Override
-    public Expression getTenantId() {
-        return new LongValue(TenantContextHolder.getRequiredTenantId());
-    }
-
-    @Override
-    public boolean ignoreTable(String tableName) {
-        return TenantContextHolder.isIgnore() // 情况一,全局忽略多租户
-            || CollUtil.contains(ignoreTables, tableName); // 情况二,忽略多租户的表
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/DataDS.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/DataDS.java
deleted file mode 100644
index fce0fbb..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/DataDS.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.tenant.core.db.dynamic;
-
-import com.baomidou.dynamic.datasource.annotation.DS;
-
-import java.lang.annotation.*;
-
-/**
- * 使用数据源所在的数据源
- *
- * 使用方式:当我们希望一个表使用租户所在的数据源,可以在该表的 Mapper 上添加该注解
- *
- * @author 芋道源码
- */
-@Target({ElementType.TYPE, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@DS(DataDS.KEY)
-public @interface DataDS {
-
-    /**
-     * 数据源的占位符
-     */
-    String KEY = "#context.dataSourceId";
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/TenantDS.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/TenantDS.java
deleted file mode 100644
index bf7da0c..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/TenantDS.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.tenant.core.db.dynamic;
-
-import com.baomidou.dynamic.datasource.annotation.DS;
-
-import java.lang.annotation.*;
-
-/**
- * 使用租户所在的数据源
- *
- * 使用方式:当我们希望一个表使用租户所在的数据源,可以在该表的 Mapper 上添加该注解
- *
- * @author 芋道源码
- */
-@Target({ElementType.TYPE, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@DS(TenantDS.KEY)
-public @interface TenantDS {
-
-    /**
-     * 租户对应的数据源的占位符
-     */
-    String KEY = "#context.tenantId";
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/TenantDsProcessor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/TenantDsProcessor.java
deleted file mode 100644
index 24b2eff..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/db/dynamic/TenantDsProcessor.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.iailab.framework.tenant.core.db.dynamic;
-
-import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
-import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
-import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
-import com.baomidou.dynamic.datasource.processor.DsProcessor;
-import com.iailab.framework.tenant.core.context.DataContextHolder;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.tenant.core.service.TenantFrameworkService;
-import com.iailab.module.infra.api.db.DataSourceConfigServiceApi;
-import com.iailab.module.infra.api.db.dto.DataSourceConfigRespDTO;
-import lombok.RequiredArgsConstructor;
-import org.aopalliance.intercept.MethodInvocation;
-import org.springframework.context.annotation.Lazy;
-
-import javax.annotation.Resource;
-import javax.sql.DataSource;
-import java.util.Objects;
-
-/**
- * 基于 {@link TenantDS} 的数据源处理器
- *
- * 1. 如果有 @TenantDS 注解,返回该租户的数据源
- * 2. 如果该租户的数据源未创建,则进行创建
- *
- * @author 芋道源码
- */
-@RequiredArgsConstructor
-public class TenantDsProcessor extends DsProcessor {
-
-    /**
-     * 用于获取租户数据源配置的 Service
-     */
-    @Resource
-    @Lazy
-    private TenantFrameworkService tenantFrameworkService;
-
-    /**
-     * 动态数据源
-     */
-    @Resource
-    @Lazy  // 为什么添加 @Lazy 注解?因为它和 DynamicRoutingDataSource 相互依赖,导致无法初始化
-    private DynamicRoutingDataSource dynamicRoutingDataSource;
-
-    /**
-     * 用于创建租户数据源的 Creator
-     */
-    @Resource
-    @Lazy
-    private DefaultDataSourceCreator dataSourceCreator;
-
-    @Resource
-    @Lazy
-    private DataSourceConfigServiceApi dataSourceConfigServiceApi;
-
-    @Override
-    public boolean matches(String key) {
-        return Objects.equals(key, TenantDS.KEY) || Objects.equals(key, DataDS.KEY);
-    }
-
-    @Override
-    public String doDetermineDatasource(MethodInvocation invocation, String key) {
-        if (DataDS.KEY.equals(key)){
-            // 获得数据源配置
-            Long dataSourceId = DataContextHolder.getRequiredDataSourceId();
-            DataSourceConfigRespDTO dataSourceConfigRespDTO = dataSourceConfigServiceApi.getDataSourceConfig(dataSourceId);
-            DataSourceProperty dataSourceProperty = new DataSourceProperty();
-            dataSourceProperty.setPoolName(dataSourceConfigRespDTO.getName());
-            dataSourceProperty.setUrl(dataSourceConfigRespDTO.getUrl());
-            dataSourceProperty.setUsername(dataSourceConfigRespDTO.getUsername());
-            dataSourceProperty.setPassword(dataSourceConfigRespDTO.getPassword());
-            // 创建 or 创建数据源,并返回数据源名字
-            return createDatasourceIfAbsent(dataSourceProperty);
-        }else if(TenantDS.KEY.equals(key)){
-            // 获得数据源配置
-            Long tenantId = TenantContextHolder.getRequiredTenantId();
-            DataSourceProperty dataSourceProperty = tenantFrameworkService.getDataSourceProperty(tenantId);
-            // 创建 or 创建数据源,并返回数据源名字
-            return createDatasourceIfAbsent(dataSourceProperty);
-        }
-        return key;
-    }
-
-    private String createDatasourceIfAbsent(DataSourceProperty dataSourceProperty) {
-        // 1. 重点:如果数据源不存在,则进行创建
-        if (isDataSourceNotExist(dataSourceProperty)) {
-            // 问题一:为什么要加锁?因为,如果多个线程同时执行到这里,会导致多次创建数据源
-            // 问题二:为什么要使用 poolName 加锁?保证多个不同的 poolName 可以并发创建数据源
-            // 问题三:为什么要使用 intern 方法?因为,intern 方法,会返回一个字符串的常量池中的引用
-            // intern 的说明,可见 https://www.cnblogs.com/xrq730/p/6662232.html 文章
-            synchronized (dataSourceProperty.getPoolName().intern()) {
-                if (isDataSourceNotExist(dataSourceProperty)) {
-                    DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
-                    dynamicRoutingDataSource.addDataSource(dataSourceProperty.getPoolName(), dataSource);
-                }
-            }
-        }
-        // 2. 返回数据源的名字
-        return dataSourceProperty.getPoolName();
-    }
-
-    private boolean isDataSourceNotExist(DataSourceProperty dataSourceProperty) {
-        return !dynamicRoutingDataSource.getDataSources().containsKey(dataSourceProperty.getPoolName());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/job/TenantJob.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/job/TenantJob.java
deleted file mode 100644
index fd790d7..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/job/TenantJob.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.iailab.framework.tenant.core.job;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 多租户 Job 注解
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface TenantJob {
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/job/TenantJobAspect.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/job/TenantJobAspect.java
deleted file mode 100644
index 5d7a9ac..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/job/TenantJobAspect.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.iailab.framework.tenant.core.job;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.tenant.core.service.TenantFrameworkService;
-import com.iailab.framework.tenant.core.util.TenantUtils;
-import com.xxl.job.core.context.XxlJobHelper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 多租户 JobHandler AOP
- * 任务执行时,会按照租户逐个执行 Job 的逻辑
- *
- * 注意,需要保证 JobHandler 的幂等性。因为 Job 因为某个租户执行失败重试时,之前执行成功的租户也会再次执行。
- *
- * @author iailab
- */
-@Aspect
-@RequiredArgsConstructor
-@Slf4j
-public class TenantJobAspect {
-
-    private final TenantFrameworkService tenantFrameworkService;
-
-    @Around("@annotation(tenantJob)")
-    public void around(ProceedingJoinPoint joinPoint, TenantJob tenantJob) {
-        // 获得租户列表
-        List<Long> tenantIds = tenantFrameworkService.getTenantIds();
-        if (CollUtil.isEmpty(tenantIds)) {
-            return;
-        }
-
-        // 逐个租户,执行 Job
-        Map<Long, String> results = new ConcurrentHashMap<>();
-        tenantIds.parallelStream().forEach(tenantId -> {
-            // TODO iailab:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况
-            TenantUtils.execute(tenantId, () -> {
-                try {
-                    System.out.println("租户id:" + tenantId);
-                    joinPoint.proceed();
-                } catch (Throwable e) {
-                    results.put(tenantId, ExceptionUtil.getRootCauseMessage(e));
-                    // 打印异常
-                    XxlJobHelper.log(StrUtil.format("[多租户({}) 执行任务({}),发生异常:{}]",
-                            tenantId, joinPoint.getSignature(), ExceptionUtils.getStackTrace(e)));
-                }
-            });
-        });
-        // 如果 results 非空,说明发生了异常,标记 XXL-Job 执行失败
-        if (CollUtil.isNotEmpty(results)) {
-            XxlJobHelper.handleFail(JsonUtils.toJsonString(results));
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java
deleted file mode 100644
index 480b4c6..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/kafka/TenantKafkaEnvironmentPostProcessor.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.tenant.core.mq.kafka;
-
-import cn.hutool.core.util.StrUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.env.EnvironmentPostProcessor;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-/**
- * 多租户的 Kafka 的 {@link EnvironmentPostProcessor} 实现类
- *
- * Kafka Producer 发送消息时,增加 {@link TenantKafkaProducerInterceptor} 拦截器
- *
- * @author iailab
- */
-@Slf4j
-public class TenantKafkaEnvironmentPostProcessor implements EnvironmentPostProcessor {
-
-    private static final String PROPERTY_KEY_INTERCEPTOR_CLASSES = "spring.kafka.producer.properties.interceptor.classes";
-
-    @Override
-    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
-        // 添加 TenantKafkaProducerInterceptor 拦截器
-        try {
-            String value = environment.getProperty(PROPERTY_KEY_INTERCEPTOR_CLASSES);
-            if (StrUtil.isEmpty(value)) {
-                value = TenantKafkaProducerInterceptor.class.getName();
-            } else {
-                value += "," + TenantKafkaProducerInterceptor.class.getName();
-            }
-            environment.getSystemProperties().put(PROPERTY_KEY_INTERCEPTOR_CLASSES, value);
-        } catch (NoClassDefFoundError ignore) {
-            // 如果触发 NoClassDefFoundError 异常,说明 TenantKafkaProducerInterceptor 类不存在,即没引入 kafka-spring 依赖
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java
deleted file mode 100644
index 6bdcec3..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/kafka/TenantKafkaProducerInterceptor.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.iailab.framework.tenant.core.mq.kafka;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import org.apache.kafka.clients.producer.ProducerInterceptor;
-import org.apache.kafka.clients.producer.ProducerRecord;
-import org.apache.kafka.clients.producer.RecordMetadata;
-import org.apache.kafka.common.header.Headers;
-import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
-
-import java.util.Map;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * Kafka 消息队列的多租户 {@link ProducerInterceptor} 实现类
- *
- * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
- * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
- *
- * @author iailab
- */
-public class TenantKafkaProducerInterceptor implements ProducerInterceptor<Object, Object> {
-
-    @Override
-    public ProducerRecord<Object, Object> onSend(ProducerRecord<Object, Object> record) {
-        Long tenantId = TenantContextHolder.getTenantId();
-        if (tenantId != null) {
-            Headers headers = (Headers) ReflectUtil.getFieldValue(record, "headers"); // private 属性,没有 get 方法,智能反射
-            headers.add(HEADER_TENANT_ID, tenantId.toString().getBytes());
-        }
-        return record;
-    }
-
-    @Override
-    public void onAcknowledgement(RecordMetadata metadata, Exception exception) {
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public void configure(Map<String, ?> configs) {
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rabbitmq/TenantRabbitMQInitializer.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rabbitmq/TenantRabbitMQInitializer.java
deleted file mode 100644
index b990d14..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rabbitmq/TenantRabbitMQInitializer.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.iailab.framework.tenant.core.mq.rabbitmq;
-
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-
-/**
- * 多租户的 RabbitMQ 初始化器
- *
- * @author iailab
- */
-public class TenantRabbitMQInitializer implements BeanPostProcessor {
-
-    @Override
-    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-        if (bean instanceof RabbitTemplate) {
-            RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
-            rabbitTemplate.addBeforePublishPostProcessors(new TenantRabbitMQMessagePostProcessor());
-        }
-        return bean;
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rabbitmq/TenantRabbitMQMessagePostProcessor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rabbitmq/TenantRabbitMQMessagePostProcessor.java
deleted file mode 100644
index 577ae3d..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rabbitmq/TenantRabbitMQMessagePostProcessor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.iailab.framework.tenant.core.mq.rabbitmq;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import org.apache.kafka.clients.producer.ProducerInterceptor;
-import org.springframework.amqp.AmqpException;
-import org.springframework.amqp.core.Message;
-import org.springframework.amqp.core.MessagePostProcessor;
-import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * RabbitMQ 消息队列的多租户 {@link ProducerInterceptor} 实现类
- *
- * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
- * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
- *
- * @author iailab
- */
-public class TenantRabbitMQMessagePostProcessor implements MessagePostProcessor {
-
-    @Override
-    public Message postProcessMessage(Message message) throws AmqpException {
-        Long tenantId = TenantContextHolder.getTenantId();
-        if (tenantId != null) {
-            message.getMessageProperties().getHeaders().put(HEADER_TENANT_ID, tenantId);
-        }
-        return message;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/redis/TenantRedisMessageInterceptor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/redis/TenantRedisMessageInterceptor.java
deleted file mode 100644
index 1c7ad18..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/redis/TenantRedisMessageInterceptor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.framework.tenant.core.mq.redis;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * 多租户 {@link AbstractRedisMessage} 拦截器
- *
- * 1. Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
- * 2. Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中
- *
- * @author iailab
- */
-public class TenantRedisMessageInterceptor implements RedisMessageInterceptor {
-
-    @Override
-    public void sendMessageBefore(AbstractRedisMessage message) {
-        Long tenantId = TenantContextHolder.getTenantId();
-        if (tenantId != null) {
-            message.addHeader(HEADER_TENANT_ID, tenantId.toString());
-        }
-    }
-
-    @Override
-    public void consumeMessageBefore(AbstractRedisMessage message) {
-        String tenantIdStr = message.getHeader(HEADER_TENANT_ID);
-        if (StrUtil.isNotEmpty(tenantIdStr)) {
-            TenantContextHolder.setTenantId(Long.valueOf(tenantIdStr));
-        }
-    }
-
-    @Override
-    public void consumeMessageAfter(AbstractRedisMessage message) {
-        // 注意,Consumer 是一个逻辑的入口,所以不考虑原本上下文就存在租户编号的情况
-        TenantContextHolder.clear();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQConsumeMessageHook.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQConsumeMessageHook.java
deleted file mode 100644
index c934b21..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQConsumeMessageHook.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.tenant.core.mq.rocketmq;
-
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import org.apache.rocketmq.client.hook.ConsumeMessageContext;
-import org.apache.rocketmq.client.hook.ConsumeMessageHook;
-import org.apache.rocketmq.common.message.MessageExt;
-import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
-
-import java.util.List;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * RocketMQ 消息队列的多租户 {@link ConsumeMessageHook} 实现类
- *
- * Consumer 消费消息时,将消息的 Header 的租户编号,添加到 {@link TenantContextHolder} 中,通过 {@link InvocableHandlerMethod} 实现
- *
- * @author iailab
- */
-public class TenantRocketMQConsumeMessageHook implements ConsumeMessageHook {
-
-    @Override
-    public String hookName() {
-        return getClass().getSimpleName();
-    }
-
-    @Override
-    public void consumeMessageBefore(ConsumeMessageContext context) {
-        // 校验,消息必须是单条,不然设置租户可能不正确
-        List<MessageExt> messages = context.getMsgList();
-        Assert.isTrue(messages.size() == 1, "消息条数({})不正确", messages.size());
-        // 设置租户编号
-        String tenantId = messages.get(0).getUserProperty(HEADER_TENANT_ID);
-        if (StrUtil.isNotEmpty(tenantId)) {
-            TenantContextHolder.setTenantId(Long.parseLong(tenantId));
-        }
-    }
-
-    @Override
-    public void consumeMessageAfter(ConsumeMessageContext context) {
-        TenantContextHolder.clear();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQInitializer.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQInitializer.java
deleted file mode 100644
index eab04d7..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQInitializer.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.iailab.framework.tenant.core.mq.rocketmq;
-
-import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
-import org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl;
-import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
-import org.apache.rocketmq.client.producer.DefaultMQProducer;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-
-/**
- * 多租户的 RocketMQ 初始化器
- *
- * @author iailab
- */
-public class TenantRocketMQInitializer implements BeanPostProcessor {
-
-    @Override
-    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-        if (bean instanceof DefaultRocketMQListenerContainer) {
-            DefaultRocketMQListenerContainer container = (DefaultRocketMQListenerContainer) bean;
-            initTenantConsumer(container.getConsumer());
-        } else if (bean instanceof RocketMQTemplate) {
-            RocketMQTemplate template = (RocketMQTemplate) bean;
-            initTenantProducer(template.getProducer());
-        }
-        return bean;
-    }
-
-    private void initTenantProducer(DefaultMQProducer producer) {
-        if (producer == null) {
-            return;
-        }
-        DefaultMQProducerImpl producerImpl = producer.getDefaultMQProducerImpl();
-        if (producerImpl == null) {
-            return;
-        }
-        producerImpl.registerSendMessageHook(new TenantRocketMQSendMessageHook());
-    }
-
-    private void initTenantConsumer(DefaultMQPushConsumer consumer) {
-        if (consumer == null) {
-            return;
-        }
-        DefaultMQPushConsumerImpl consumerImpl = consumer.getDefaultMQPushConsumerImpl();
-        if (consumerImpl == null) {
-            return;
-        }
-        consumerImpl.registerConsumeMessageHook(new TenantRocketMQConsumeMessageHook());
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQSendMessageHook.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQSendMessageHook.java
deleted file mode 100644
index 6aac75d..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/mq/rocketmq/TenantRocketMQSendMessageHook.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.tenant.core.mq.rocketmq;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import org.apache.rocketmq.client.hook.SendMessageContext;
-import org.apache.rocketmq.client.hook.SendMessageHook;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * RocketMQ 消息队列的多租户 {@link SendMessageHook} 实现类
- *
- * Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
- *
- * @author iailab
- */
-public class TenantRocketMQSendMessageHook implements SendMessageHook {
-
-    @Override
-    public String hookName() {
-        return getClass().getSimpleName();
-    }
-
-    @Override
-    public void sendMessageBefore(SendMessageContext sendMessageContext) {
-        Long tenantId = TenantContextHolder.getTenantId();
-        if (tenantId == null) {
-            return;
-        }
-        sendMessageContext.getMessage().putUserProperty(HEADER_TENANT_ID, tenantId.toString());
-    }
-
-    @Override
-    public void sendMessageAfter(SendMessageContext sendMessageContext) {
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/redis/TenantRedisCacheManager.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/redis/TenantRedisCacheManager.java
deleted file mode 100644
index 9394cf2..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/redis/TenantRedisCacheManager.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.tenant.core.redis;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.redis.core.TimeoutRedisCacheManager;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.cache.Cache;
-import org.springframework.data.redis.cache.RedisCacheConfiguration;
-import org.springframework.data.redis.cache.RedisCacheManager;
-import org.springframework.data.redis.cache.RedisCacheWriter;
-
-import java.util.Set;
-
-/**
- * 多租户的 {@link RedisCacheManager} 实现类
- *
- * 操作指定 name 的 {@link Cache} 时,自动拼接租户后缀,格式为 name + ":" + tenantId + 后缀
- *
- * @author airhead
- */
-@Slf4j
-public class TenantRedisCacheManager extends TimeoutRedisCacheManager {
-
-    private final Set<String> ignoreCaches;
-
-    public TenantRedisCacheManager(RedisCacheWriter cacheWriter,
-                                   RedisCacheConfiguration defaultCacheConfiguration,
-                                   Set<String> ignoreCaches) {
-        super(cacheWriter, defaultCacheConfiguration);
-        this.ignoreCaches = ignoreCaches;
-    }
-
-    @Override
-    public Cache getCache(String name) {
-        // 如果开启多租户,则 name 拼接租户后缀
-        if (!TenantContextHolder.isIgnore()
-                && TenantContextHolder.getTenantId() != null
-                && !CollUtil.contains(ignoreCaches, name)) {
-            name = name + ":" + TenantContextHolder.getTenantId();
-        }
-
-        // 继续基于父方法
-        return super.getCache(name);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/rpc/TenantRequestInterceptor.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/rpc/TenantRequestInterceptor.java
deleted file mode 100644
index afb26f8..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/rpc/TenantRequestInterceptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.tenant.core.rpc;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import feign.RequestInterceptor;
-import feign.RequestTemplate;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * Tenant 的 RequestInterceptor 实现类:Feign 请求时,将 {@link TenantContextHolder} 设置到 header 中,继续透传给被调用的服务
- *
- * @author iailab
- */
-public class TenantRequestInterceptor implements RequestInterceptor {
-
-    @Override
-    public void apply(RequestTemplate requestTemplate) {
-        Long tenantId = TenantContextHolder.getTenantId();
-        if (tenantId != null) {
-            requestTemplate.header(HEADER_TENANT_ID, String.valueOf(tenantId));
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/security/TenantSecurityWebFilter.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/security/TenantSecurityWebFilter.java
deleted file mode 100644
index bab0e73..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/security/TenantSecurityWebFilter.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.iailab.framework.tenant.core.security;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.framework.tenant.config.TenantProperties;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.tenant.core.service.TenantFrameworkService;
-import com.iailab.framework.web.config.WebProperties;
-import com.iailab.framework.web.core.filter.ApiRequestFilter;
-import com.iailab.framework.web.core.handler.GlobalExceptionHandler;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.AntPathMatcher;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * 多租户 Security Web 过滤器
- * 1. 如果是登陆的用户,校验是否有权限访问该租户,避免越权问题。
- * 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。
- * 3. 校验租户是合法,例如说被禁用、到期
- *
- * @author iailab
- */
-@Slf4j
-public class TenantSecurityWebFilter extends ApiRequestFilter {
-
-    private final TenantProperties tenantProperties;
-
-    private final AntPathMatcher pathMatcher;
-
-    private final GlobalExceptionHandler globalExceptionHandler;
-    private final TenantFrameworkService tenantFrameworkService;
-
-    public TenantSecurityWebFilter(TenantProperties tenantProperties,
-                                   WebProperties webProperties,
-                                   GlobalExceptionHandler globalExceptionHandler,
-                                   TenantFrameworkService tenantFrameworkService) {
-        super(webProperties);
-        this.tenantProperties = tenantProperties;
-        this.pathMatcher = new AntPathMatcher();
-        this.globalExceptionHandler = globalExceptionHandler;
-        this.tenantFrameworkService = tenantFrameworkService;
-    }
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        Long tenantId = TenantContextHolder.getTenantId();
-        // 1. 登陆的用户,校验是否有权限访问该租户,避免越权问题。
-        LoginUser user = SecurityFrameworkUtils.getLoginUser();
-        if (user != null) {
-            // 如果获取不到租户编号,则尝试使用登陆用户的租户编号
-            if (tenantId == null) {
-                tenantId = user.getTenantId();
-                TenantContextHolder.setTenantId(tenantId);
-            // 如果传递了租户编号,则进行比对租户编号,避免越权问题
-            } else if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId())) {
-                log.error("[doFilterInternal][租户({}) User({}/{}) 越权访问租户({}) URL({}/{})]",
-                        user.getTenantId(), user.getId(), user.getUserType(),
-                        TenantContextHolder.getTenantId(), request.getRequestURI(), request.getMethod());
-                ServletUtils.writeJSON(response, CommonResult.error(GlobalErrorCodeConstants.FORBIDDEN.getCode(),
-                        "您无权访问该租户的数据"));
-                return;
-            }
-        }
-
-        // 如果非允许忽略租户的 URL,则校验租户是否合法
-        if (!isIgnoreUrl(request)) {
-            // 2. 如果请求未带租户的编号,不允许访问。
-            if (tenantId == null) {
-                log.error("[doFilterInternal][URL({}/{}) 未传递租户编号]", request.getRequestURI(), request.getMethod());
-                ServletUtils.writeJSON(response, CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
-                        "请求的租户标识未传递,请进行排查"));
-                return;
-            }
-            // 3. 校验租户是合法,例如说被禁用、到期
-            try {
-                tenantFrameworkService.validTenant(tenantId);
-            } catch (Throwable ex) {
-                CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
-                ServletUtils.writeJSON(response, result);
-                return;
-            }
-        } else { // 如果是允许忽略租户的 URL,若未传递租户编号,则默认忽略租户编号,避免报错
-            if (tenantId == null) {
-                TenantContextHolder.setIgnore(true);
-            }
-        }
-
-        // 继续过滤
-        chain.doFilter(request, response);
-    }
-
-    private boolean isIgnoreUrl(HttpServletRequest request) {
-        // 快速匹配,保证性能
-        if (CollUtil.contains(tenantProperties.getIgnoreUrls(), request.getRequestURI())) {
-            return true;
-        }
-        // 逐个 Ant 路径匹配
-        for (String url : tenantProperties.getIgnoreUrls()) {
-            if (pathMatcher.match(url, request.getRequestURI())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/service/TenantFrameworkService.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/service/TenantFrameworkService.java
deleted file mode 100644
index 92ed16a..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/service/TenantFrameworkService.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.tenant.core.service;
-
-import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
-
-import java.util.List;
-
-/**
- * Tenant 框架 Service 接口,定义获取租户信息
- *
- * @author iailab
- */
-public interface TenantFrameworkService {
-
-    /**
-     * 获得所有租户
-     *
-     * @return 租户编号数组
-     */
-    List<Long> getTenantIds();
-
-    /**
-     * 校验租户是否合法
-     *
-     * @param id 租户编号
-     */
-    void validTenant(Long id);
-
-    /**
-     * 获得租户对应的数据源配置
-     *
-     * @param id 租户编号
-     * @return 数据源配置
-     */
-    DataSourceProperty getDataSourceProperty(Long id);
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/service/TenantFrameworkServiceImpl.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/service/TenantFrameworkServiceImpl.java
deleted file mode 100644
index eef1cf4..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/service/TenantFrameworkServiceImpl.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.iailab.framework.tenant.core.service;
-
-import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.cache.CacheUtils;
-import com.iailab.module.system.api.tenant.TenantApi;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-import com.iailab.module.system.api.tenant.dto.TenantDataSourceConfigRespDTO;
-import lombok.RequiredArgsConstructor;
-import lombok.SneakyThrows;
-
-import java.time.Duration;
-import java.util.List;
-
-import static com.iailab.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
-
-/**
- * Tenant 框架 Service 实现类
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public class TenantFrameworkServiceImpl implements TenantFrameworkService {
-
-    private final TenantApi tenantApi;
-
-    /**
-     * 针对 {@link #getTenantIds()} 的缓存
-     */
-    private final LoadingCache<Object, List<Long>> getTenantIdsCache = buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<Object, List<Long>>() {
-
-                @Override
-                public List<Long> load(Object key) {
-                    return tenantApi.getTenantIdList().getCheckedData();
-                }
-
-            });
-
-    /**
-     * 针对 {@link #validTenant(Long)} 的缓存
-     */
-    private final LoadingCache<Long, CommonResult<Boolean>> validTenantCache = buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<Long, CommonResult<Boolean>>() {
-
-                @Override
-                public CommonResult<Boolean> load(Long id) {
-                    return tenantApi.validTenant(id);
-                }
-
-            });
-
-    /**
-     * 针对 {@link #getDataSourceProperty(Long)} 的缓存
-     */
-    private final LoadingCache<Long, DataSourceProperty> dataSourcePropertyCache = CacheUtils.buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<Long, DataSourceProperty>() {
-
-                @Override
-                public DataSourceProperty load(Long id) {
-                    // 获得租户对应的数据源配置
-                    TenantDataSourceConfigRespDTO dataSourceConfig = tenantApi.getTenantDataSourceConfig(id);
-                    if (dataSourceConfig == null) {
-                        return null;
-                    }
-                    // 转换成 dynamic-datasource 配置
-//                    return new DataSourceProperty()
-//                            .setPoolName(dataSourceConfig.getName()).setUrl(dataSourceConfig.getUrl())
-//                            .setUsername(dataSourceConfig.getUsername()).setPassword(dataSourceConfig.getPassword());
-
-                    DataSourceProperty ds = new DataSourceProperty();
-                    ds.setPoolName(dataSourceConfig.getName());
-                    ds.setUrl(dataSourceConfig.getUrl());
-                    ds.setUsername(dataSourceConfig.getUsername());
-                    ds.setPassword(dataSourceConfig.getPassword());
-                    return ds;
-                }
-
-            });
-
-    @Override
-    @SneakyThrows
-    public List<Long> getTenantIds() {
-        return getTenantIdsCache.get(Boolean.TRUE);
-    }
-
-    @Override
-    @SneakyThrows
-    public void validTenant(Long id) {
-        validTenantCache.get(id).checkError();
-    }
-
-    @Override
-    @SneakyThrows
-    public DataSourceProperty getDataSourceProperty(Long id) {
-        return dataSourcePropertyCache.get(id);
-    }
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/util/TenantUtils.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/util/TenantUtils.java
deleted file mode 100644
index 6f830cd..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/util/TenantUtils.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.iailab.framework.tenant.core.util;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * 多租户 Util
- *
- * @author iailab
- */
-public class TenantUtils {
-
-    /**
-     * 使用指定租户,执行对应的逻辑
-     *
-     * 注意,如果当前是忽略租户的情况下,会被强制设置成不忽略租户
-     * 当然,执行完成后,还是会恢复回去
-     *
-     * @param tenantId 租户编号
-     * @param runnable 逻辑
-     */
-    public static void execute(Long tenantId, Runnable runnable) {
-        Long oldTenantId = TenantContextHolder.getTenantId();
-        Boolean oldIgnore = TenantContextHolder.isIgnore();
-        try {
-            TenantContextHolder.setTenantId(tenantId);
-            TenantContextHolder.setIgnore(false);
-            // 执行逻辑
-            runnable.run();
-        } finally {
-            TenantContextHolder.setTenantId(oldTenantId);
-            TenantContextHolder.setIgnore(oldIgnore);
-        }
-    }
-
-    /**
-     * 使用指定租户,执行对应的逻辑
-     *
-     * 注意,如果当前是忽略租户的情况下,会被强制设置成不忽略租户
-     * 当然,执行完成后,还是会恢复回去
-     *
-     * @param tenantId 租户编号
-     * @param callable 逻辑
-     */
-    public static <V> V execute(Long tenantId, Callable<V> callable) {
-        Long oldTenantId = TenantContextHolder.getTenantId();
-        Boolean oldIgnore = TenantContextHolder.isIgnore();
-        try {
-            TenantContextHolder.setTenantId(tenantId);
-            TenantContextHolder.setIgnore(false);
-            // 执行逻辑
-            return callable.call();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            TenantContextHolder.setTenantId(oldTenantId);
-            TenantContextHolder.setIgnore(oldIgnore);
-        }
-    }
-
-    /**
-     * 忽略租户,执行对应的逻辑
-     *
-     * @param runnable 逻辑
-     */
-    public static void executeIgnore(Runnable runnable) {
-        Boolean oldIgnore = TenantContextHolder.isIgnore();
-        try {
-            TenantContextHolder.setIgnore(true);
-            // 执行逻辑
-            runnable.run();
-        } finally {
-            TenantContextHolder.setIgnore(oldIgnore);
-        }
-    }
-
-    /**
-     * 将多租户编号,添加到 header 中
-     *
-     * @param headers HTTP 请求 headers
-     * @param tenantId 租户编号
-     */
-    public static void addTenantHeader(Map<String, String> headers, Long tenantId) {
-        if (tenantId != null) {
-            headers.put(HEADER_TENANT_ID, tenantId.toString());
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/web/TenantContextWebFilter.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/web/TenantContextWebFilter.java
deleted file mode 100644
index 4973691..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/core/web/TenantContextWebFilter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.tenant.core.web;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * 多租户 Context Web 过滤器
- * 将请求 Header 中的 tenant-id 解析出来,添加到 {@link TenantContextHolder} 中,这样后续的 DB 等操作,可以获得到租户编号。
- *
- * @author iailab
- */
-public class TenantContextWebFilter extends OncePerRequestFilter {
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        // 设置
-        Long tenantId = WebFrameworkUtils.getTenantId(request);
-        if (tenantId != null) {
-            TenantContextHolder.setTenantId(tenantId);
-        }
-        try {
-            chain.doFilter(request, response);
-        } finally {
-            // 清理
-            TenantContextHolder.clear();
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/package-info.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/package-info.java
deleted file mode 100644
index eaefcd7..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/com/iailab/framework/tenant/package-info.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * 多租户,支持如下层面:
- * 1. DB:基于 MyBatis Plus 多租户的功能实现。
- * 2. Redis:通过在 Redis Key 上拼接租户编号的方式,进行隔离。
- * 3. Web:请求 HTTP API 时,解析 Header 的 tenant-id 租户编号,添加到租户上下文。
- * 4. Security:校验当前登陆的用户,是否越权访问其它租户的数据。
- * 5. Job:在 JobHandler 执行任务时,会按照每个租户,都独立并行执行一次。
- * 6. MQ:在 Producer 发送消息时,Header 带上 tenant-id 租户编号;在 Consumer 消费消息时,将 Header 的 tenant-id 租户编号,添加到租户上下文。
- * 7. Async:异步需要保证 ThreadLocal 的传递性,通过使用阿里开源的 TransmittableThreadLocal 实现。相关的改造点,可见:
- *      1)Spring Async:
- *          {@link com.iailab.framework.quartz.config.IailabAsyncAutoConfiguration#threadPoolTaskExecutorBeanPostProcessor()}
- *      2)Spring Security:
- *          TransmittableThreadLocalSecurityContextHolderStrategy
- *          和 IailabSecurityAutoConfiguration#securityContextHolderMethodInvokingFactoryBean() 方法
- *
- */
-package com.iailab.framework.tenant;
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/iailab-framework/iailab-common-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java
deleted file mode 100644
index 6f282a2..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.messaging.handler.invocation;
-
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.tenant.core.util.TenantUtils;
-import org.springframework.core.DefaultParameterNameDiscoverer;
-import org.springframework.core.MethodParameter;
-import org.springframework.core.ParameterNameDiscoverer;
-import org.springframework.core.ResolvableType;
-import org.springframework.lang.Nullable;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.handler.HandlerMethod;
-import org.springframework.util.ObjectUtils;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * Extension of {@link HandlerMethod} that invokes the underlying method with
- * argument values resolved from the current HTTP request through a list of
- * {@link HandlerMethodArgumentResolver}.
- *
- * 针对 rabbitmq-spring 和 kafka-spring,不存在合适的拓展点,可以实现 Consumer 消费前,读取 Header 中的 tenant-id 设置到 {@link TenantContextHolder} 中
- * TODO iailab:持续跟进,看看有没新的拓展点
- *
- * @author Rossen Stoyanchev
- * @author Juergen Hoeller
- * @since 4.0
- */
-public class InvocableHandlerMethod extends HandlerMethod {
-
-    private static final Object[] EMPTY_ARGS = new Object[0];
-
-    private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
-
-    private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
-
-    /**
-     * Create an instance from a {@code HandlerMethod}.
-     */
-    public InvocableHandlerMethod(HandlerMethod handlerMethod) {
-        super(handlerMethod);
-    }
-
-    /**
-     * Create an instance from a bean instance and a method.
-     */
-    public InvocableHandlerMethod(Object bean, Method method) {
-        super(bean, method);
-    }
-
-    /**
-     * Construct a new handler method with the given bean instance, method name and parameters.
-     * @param bean the object bean
-     * @param methodName the method name
-     * @param parameterTypes the method parameter types
-     * @throws NoSuchMethodException when the method cannot be found
-     */
-    public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
-            throws NoSuchMethodException {
-
-        super(bean, methodName, parameterTypes);
-    }
-
-    /**
-     * Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values.
-     */
-    public void setMessageMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
-        this.resolvers = argumentResolvers;
-    }
-
-    /**
-     * Set the ParameterNameDiscoverer for resolving parameter names when needed
-     * (e.g. default request attribute name).
-     * <p>Default is a {@link DefaultParameterNameDiscoverer}.
-     */
-    public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
-        this.parameterNameDiscoverer = parameterNameDiscoverer;
-    }
-
-    /**
-     * Invoke the method after resolving its argument values in the context of the given message.
-     * <p>Argument values are commonly resolved through
-     * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}.
-     * The {@code providedArgs} parameter however may supply argument values to be used directly,
-     * i.e. without argument resolution.
-     * <p>Delegates to {@link #getMethodArgumentValues} and calls {@link #doInvoke} with the
-     * resolved arguments.
-     * @param message the current message being processed
-     * @param providedArgs "given" arguments matched by type, not resolved
-     * @return the raw value returned by the invoked method
-     * @throws Exception raised if no suitable argument resolver can be found,
-     * or if the method raised an exception
-     * @see #getMethodArgumentValues
-     * @see #doInvoke
-     */
-    @Nullable
-    public Object invoke(Message<?> message, Object... providedArgs) throws Exception {
-        Object[] args = getMethodArgumentValues(message, providedArgs);
-        if (logger.isTraceEnabled()) {
-            logger.trace("Arguments: " + Arrays.toString(args));
-        }
-        // 注意:如下是本类的改动点!!!
-        // 情况一:无租户编号的情况
-        Long tenantId= parseTenantId(message);
-        if (tenantId == null) {
-            return doInvoke(args);
-        }
-        // 情况二:有租户的情况下
-        return TenantUtils.execute(tenantId, () -> doInvoke(args));
-    }
-
-    private Long parseTenantId(Message<?> message) {
-        Object tenantId = message.getHeaders().get(HEADER_TENANT_ID);
-        if (tenantId == null) {
-            return null;
-        }
-        if (tenantId instanceof Long) {
-            return (Long) tenantId;
-        }
-        if (tenantId instanceof Number) {
-            return ((Number) tenantId).longValue();
-        }
-        if (tenantId instanceof String) {
-            return Long.parseLong((String) tenantId);
-        }
-        if (tenantId instanceof byte[]) {
-            return Long.parseLong(new String((byte[]) tenantId));
-        }
-        throw new IllegalArgumentException("未知的数据类型:" + tenantId);
-    }
-
-    /**
-     * Get the method argument values for the current message, checking the provided
-     * argument values and falling back to the configured argument resolvers.
-     * <p>The resulting array will be passed into {@link #doInvoke}.
-     * @since 5.1.2
-     */
-    protected Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception {
-        MethodParameter[] parameters = getMethodParameters();
-        if (ObjectUtils.isEmpty(parameters)) {
-            return EMPTY_ARGS;
-        }
-
-        Object[] args = new Object[parameters.length];
-        for (int i = 0; i < parameters.length; i++) {
-            MethodParameter parameter = parameters[i];
-            parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
-            args[i] = findProvidedArgument(parameter, providedArgs);
-            if (args[i] != null) {
-                continue;
-            }
-            if (!this.resolvers.supportsParameter(parameter)) {
-                throw new MethodArgumentResolutionException(
-                        message, parameter, formatArgumentError(parameter, "No suitable resolver"));
-            }
-            try {
-                args[i] = this.resolvers.resolveArgument(parameter, message);
-            }
-            catch (Exception ex) {
-                // Leave stack trace for later, exception may actually be resolved and handled...
-                if (logger.isDebugEnabled()) {
-                    String exMsg = ex.getMessage();
-                    if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
-                        logger.debug(formatArgumentError(parameter, exMsg));
-                    }
-                }
-                throw ex;
-            }
-        }
-        return args;
-    }
-
-    /**
-     * Invoke the handler method with the given argument values.
-     */
-    @Nullable
-    protected Object doInvoke(Object... args) throws Exception {
-        try {
-            return getBridgedMethod().invoke(getBean(), args);
-        }
-        catch (IllegalArgumentException ex) {
-            assertTargetBean(getBridgedMethod(), getBean(), args);
-            String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
-            throw new IllegalStateException(formatInvokeError(text, args), ex);
-        }
-        catch (InvocationTargetException ex) {
-            // Unwrap for HandlerExceptionResolvers ...
-            Throwable targetException = ex.getTargetException();
-            if (targetException instanceof RuntimeException) {
-                throw (RuntimeException) targetException;
-            }
-            else if (targetException instanceof Error) {
-                throw (Error) targetException;
-            }
-            else if (targetException instanceof Exception) {
-                throw (Exception) targetException;
-            }
-            else {
-                throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
-            }
-        }
-    }
-
-    MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
-        return new AsyncResultMethodParameter(returnValue);
-    }
-
-    private class AsyncResultMethodParameter extends HandlerMethodParameter {
-
-        @Nullable
-        private final Object returnValue;
-
-        private final ResolvableType returnType;
-
-        public AsyncResultMethodParameter(@Nullable Object returnValue) {
-            super(-1);
-            this.returnValue = returnValue;
-            this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric();
-        }
-
-        protected AsyncResultMethodParameter(AsyncResultMethodParameter original) {
-            super(original);
-            this.returnValue = original.returnValue;
-            this.returnType = original.returnType;
-        }
-
-        @Override
-        public Class<?> getParameterType() {
-            if (this.returnValue != null) {
-                return this.returnValue.getClass();
-            }
-            if (!ResolvableType.NONE.equals(this.returnType)) {
-                return this.returnType.toClass();
-            }
-            return super.getParameterType();
-        }
-
-        @Override
-        public Type getGenericParameterType() {
-            return this.returnType.getType();
-        }
-
-        @Override
-        public AsyncResultMethodParameter clone() {
-            return new AsyncResultMethodParameter(this);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/resources/META-INF/spring.factories b/iailab-framework/iailab-common-biz-tenant/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index c03718f..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.env.EnvironmentPostProcessor=\
-  com.iailab.framework.tenant.core.mq.kafka.TenantKafkaEnvironmentPostProcessor
diff --git a/iailab-framework/iailab-common-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index b954183..0000000
--- a/iailab-framework/iailab-common-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.iailab.framework.tenant.config.IailabTenantRpcAutoConfiguration
-com.iailab.framework.tenant.config.IailabTenantAutoConfiguration
diff --git a/iailab-framework/iailab-common-env/pom.xml b/iailab-framework/iailab-common-env/pom.xml
deleted file mode 100644
index 2170152..0000000
--- a/iailab-framework/iailab-common-env/pom.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-env</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        开发环境拓展,实现类似阿里的特性环境的能力
-        1. https://segmentfault.com/a/1190000018022987
-    </description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <properties>
-        <maven.compiler.source>8</maven.compiler.source>
-        <maven.compiler.target>8</maven.compiler.target>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Spring 核心 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>jakarta.servlet</groupId>
-            <artifactId>jakarta.servlet-api</artifactId>
-        </dependency>
-
-        <!-- RPC 相关 -->
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-loadbalancer</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.github.openfeign</groupId>
-            <artifactId>feign-core</artifactId>
-        </dependency>
-
-        <!-- Registry 注册中心相关 -->
-        <dependency>
-            <groupId>com.alibaba.cloud</groupId>
-            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/EnvEnvironmentPostProcessor.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/EnvEnvironmentPostProcessor.java
deleted file mode 100644
index ace59cc..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/EnvEnvironmentPostProcessor.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.iailab.framework.env.config;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.collection.SetUtils;
-import com.iailab.framework.env.core.util.EnvUtils;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.env.EnvironmentPostProcessor;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-import java.util.Set;
-
-import static com.iailab.framework.env.core.util.EnvUtils.HOST_NAME_VALUE;
-
-/**
- * 多环境的 {@link EnvEnvironmentPostProcessor} 实现类
- * 将 iailab.env.tag 设置到 nacos 等组件对应的 tag 配置项,当且仅当它们不存在时
- *
- * @author iailab
- */
-public class EnvEnvironmentPostProcessor implements EnvironmentPostProcessor {
-
-    private static final Set<String> TARGET_TAG_KEYS = SetUtils.asSet(
-            "spring.cloud.nacos.discovery.metadata.tag" // Nacos 注册中心
-            // MQ TODO
-    );
-
-    @Override
-    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
-        // 0. 设置 ${HOST_NAME} 兜底的环境变量
-        String hostNameKey = StrUtil.subBetween(HOST_NAME_VALUE, "{", "}");
-        if (!environment.containsProperty(hostNameKey)) {
-            environment.getSystemProperties().put(hostNameKey, EnvUtils.getHostName());
-        }
-
-        // 1.1 如果没有 iailab.env.tag 配置项,则不进行配置项的修改
-        String tag = EnvUtils.getTag(environment);
-        if (StrUtil.isEmpty(tag)) {
-            return;
-        }
-        // 1.2 需要修改的配置项
-        for (String targetTagKey : TARGET_TAG_KEYS) {
-            String targetTagValue = environment.getProperty(targetTagKey);
-            if (StrUtil.isNotEmpty(targetTagValue)) {
-                continue;
-            }
-            environment.getSystemProperties().put(targetTagKey, tag);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/EnvProperties.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/EnvProperties.java
deleted file mode 100644
index b17699f..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/EnvProperties.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.env.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * 环境配置
- *
- * @author iailab
- */
-@ConfigurationProperties(prefix = "iailab.env")
-@Data
-public class EnvProperties {
-
-    public static final String TAG_KEY = "iailab.env.tag";
-
-    /**
-     * 环境标签
-     */
-    private String tag;
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/IailabEnvRpcAutoConfiguration.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/IailabEnvRpcAutoConfiguration.java
deleted file mode 100644
index ca16975..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/IailabEnvRpcAutoConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.env.config;
-
-import com.iailab.framework.env.core.fegin.EnvLoadBalancerClientFactory;
-import com.iailab.framework.env.core.fegin.EnvRequestInterceptor;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
-import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
-import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
-import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
-import org.springframework.context.annotation.Bean;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 多环境的 RPC 组件的自动配置
- *
- * @author iailab
- */
-@AutoConfiguration
-@EnableConfigurationProperties(EnvProperties.class)
-public class IailabEnvRpcAutoConfiguration {
-
-    // ========== Feign 相关 ==========
-
-    /**
-     * 创建 {@link EnvLoadBalancerClientFactory} Bean
-     *
-     * 参考 {@link LoadBalancerAutoConfiguration#loadBalancerClientFactory(LoadBalancerClientsProperties)} 方法
-     */
-    @Bean
-    public LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties,
-                                                               ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
-        EnvLoadBalancerClientFactory clientFactory = new EnvLoadBalancerClientFactory(properties);
-        clientFactory.setConfigurations(configurations.getIfAvailable(Collections::emptyList));
-        return clientFactory;
-    }
-
-    @Bean
-    public EnvRequestInterceptor envRequestInterceptor() {
-        return new EnvRequestInterceptor();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/IailabEnvWebAutoConfiguration.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/IailabEnvWebAutoConfiguration.java
deleted file mode 100644
index 10b14f3..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/config/IailabEnvWebAutoConfiguration.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.iailab.framework.env.config;
-
-import com.iailab.framework.common.enums.WebFilterOrderEnum;
-import com.iailab.framework.env.core.web.EnvWebFilter;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-
-/**
- * 多环境的 Web 组件的自动配置
- *
- * @author iailab
- */
-@AutoConfiguration
-@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
-@EnableConfigurationProperties(EnvProperties.class)
-public class IailabEnvWebAutoConfiguration {
-
-    /**
-     * 创建 {@link EnvWebFilter} Bean
-     */
-    @Bean
-    public FilterRegistrationBean<EnvWebFilter> envWebFilterFilter() {
-        EnvWebFilter filter = new EnvWebFilter();
-        FilterRegistrationBean<EnvWebFilter> bean = new FilterRegistrationBean<>(filter);
-        bean.setOrder(WebFilterOrderEnum.ENV_TAG_FILTER);
-        return bean;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/context/EnvContextHolder.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/context/EnvContextHolder.java
deleted file mode 100644
index 551db9b..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/context/EnvContextHolder.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.framework.env.core.context;
-
-import cn.hutool.core.collection.CollUtil;
-import com.alibaba.ttl.TransmittableThreadLocal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 开发环境上下文
- *
- * @author iailab
- */
-public class EnvContextHolder {
-
-    /**
-     * 标签的上下文
-     *
-     * 使用 {@link List} 的原因,可能存在多层设置或者清理
-     */
-    private static final ThreadLocal<List<String>> TAG_CONTEXT = TransmittableThreadLocal.withInitial(ArrayList::new);
-
-    public static void setTag(String tag) {
-        TAG_CONTEXT.get().add(tag);
-    }
-
-    public static String getTag() {
-        return CollUtil.getLast(TAG_CONTEXT.get());
-    }
-
-    public static void removeTag() {
-        List<String> tags = TAG_CONTEXT.get();
-        if (CollUtil.isEmpty(tags)) {
-            return;
-        }
-        tags.remove(tags.size() - 1);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java
deleted file mode 100644
index fb43806..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClient.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.iailab.framework.env.core.fegin;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.collection.CollectionUtils;
-import com.iailab.framework.env.core.context.EnvContextHolder;
-import com.iailab.framework.env.core.util.EnvUtils;
-import com.alibaba.cloud.nacos.balancer.NacosBalancer;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.loadbalancer.DefaultResponse;
-import org.springframework.cloud.client.loadbalancer.EmptyResponse;
-import org.springframework.cloud.client.loadbalancer.Request;
-import org.springframework.cloud.client.loadbalancer.Response;
-import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
-import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
-import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
-import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
-import reactor.core.publisher.Mono;
-
-import java.util.List;
-
-/**
- * 多环境的 {@link org.springframework.cloud.client.loadbalancer.LoadBalancerClient} 实现类
- * 在从服务实例列表选择时,优先选择 tag 匹配的服务实例
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-@Slf4j
-public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer {
-
-    /**
-     * 用于获取 serviceId 对应的服务实例的列表
-     */
-    private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
-    /**
-     * 需要获取的服务实例名
-     *
-     * 暂时用于打印 logger 日志
-     */
-    private final String serviceId;
-    /**
-     * 被代理的 ReactiveLoadBalancer 对象
-     */
-    private final ReactiveLoadBalancer<ServiceInstance> reactiveLoadBalancer;
-
-    @Override
-    public Mono<Response<ServiceInstance>> choose(Request request) {
-        // 情况一,没有 tag 时,使用默认的 reactiveLoadBalancer 实现负载均衡
-        String tag = EnvContextHolder.getTag();
-        if (StrUtil.isEmpty(tag)) {
-            return Mono.from(reactiveLoadBalancer.choose(request));
-        }
-
-        // 情况二,有 tag 时,使用 tag 匹配服务实例
-        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
-        return supplier.get(request).next().map(list -> getInstanceResponse(list, tag));
-    }
-
-    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, String tag) {
-        // 如果服务实例为空,则直接返回
-        if (CollUtil.isEmpty(instances)) {
-            log.warn("[getInstanceResponse][serviceId({}) 服务实例列表为空]", serviceId);
-            return new EmptyResponse();
-        }
-
-        // 筛选满足条件的实例列表
-        List<ServiceInstance> chooseInstances = CollectionUtils.filterList(instances, instance -> tag.equals(EnvUtils.getTag(instance)));
-        if (CollUtil.isEmpty(chooseInstances)) {
-            log.warn("[getInstanceResponse][serviceId({}) 没有满足 tag({}) 的服务实例列表,直接使用所有服务实例列表]", serviceId, tag);
-            chooseInstances = instances;
-        }
-
-        // TODO iailab:https://juejin.cn/post/7056770721858469896 想通网段
-
-        // 随机 + 权重获取实例列表 TODO iailab:目前直接使用 Nacos 提供的方法,如果替换注册中心,需要重新失败该方法
-        return new DefaultResponse(NacosBalancer.getHostByRandomWeight3(chooseInstances));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClientFactory.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClientFactory.java
deleted file mode 100644
index ba728f5..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvLoadBalancerClientFactory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.framework.env.core.fegin;
-
-
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
-import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
-import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
-import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
-
-/**
- * 多环境的 {@link LoadBalancerClientFactory} 实现类
- * 目的:在创建 {@link ReactiveLoadBalancer} 时,会额外增加 {@link EnvLoadBalancerClient} 代理,用于 tag 过滤服务实例
- *
- * @author iailab
- */
-public class EnvLoadBalancerClientFactory extends LoadBalancerClientFactory {
-
-    public EnvLoadBalancerClientFactory(LoadBalancerClientsProperties properties) {
-        super(properties);
-    }
-
-    @Override
-    public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) {
-        ReactiveLoadBalancer<ServiceInstance> reactiveLoadBalancer = super.getInstance(serviceId);
-        // 参考 {@link com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancerClientConfiguration#nacosLoadBalancer(Environment, LoadBalancerClientFactory, NacosDiscoveryProperties)} 方法
-        return new EnvLoadBalancerClient(super.getLazyProvider(serviceId, ServiceInstanceListSupplier.class),
-                serviceId, reactiveLoadBalancer);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvRequestInterceptor.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvRequestInterceptor.java
deleted file mode 100644
index 6242683..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/fegin/EnvRequestInterceptor.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.iailab.framework.env.core.fegin;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.env.core.context.EnvContextHolder;
-import com.iailab.framework.env.core.util.EnvUtils;
-import feign.RequestInterceptor;
-import feign.RequestTemplate;
-
-/**
- * 多环境的 {@link RequestInterceptor} 实现类:Feign 请求时,将 tag 设置到 header 中,继续透传给被调用的服务
- *
- * @author iailab
- */
-public class EnvRequestInterceptor implements RequestInterceptor {
-
-    @Override
-    public void apply(RequestTemplate requestTemplate) {
-        String tag = EnvContextHolder.getTag();
-        if (StrUtil.isNotEmpty(tag)) {
-            EnvUtils.setTag(requestTemplate, tag);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/package-info.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/package-info.java
deleted file mode 100644
index 304a953..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.iailab.framework.env.core;
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/util/EnvUtils.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/util/EnvUtils.java
deleted file mode 100644
index c010e2e..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/util/EnvUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.iailab.framework.env.core.util;
-
-import com.iailab.framework.env.config.EnvProperties;
-import feign.RequestTemplate;
-import lombok.SneakyThrows;
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.core.env.Environment;
-
-import javax.servlet.http.HttpServletRequest;
-import java.net.InetAddress;
-import java.util.Objects;
-
-/**
- * 环境 Utils
- *
- * @author iailab
- */
-public class EnvUtils {
-
-    private static final String HEADER_TAG = "tag";
-
-    public static final String HOST_NAME_VALUE = "${HOSTNAME}";
-
-    public static String getTag(HttpServletRequest request) {
-        String tag = request.getHeader(HEADER_TAG);
-        // 如果请求的是 "${HOSTNAME}",则解析成对应的本地主机名
-        // 目的:特殊逻辑,解决 IDEA Rest Client 不支持环境变量的读取,所以就服务器来做
-        return Objects.equals(tag, HOST_NAME_VALUE) ? getHostName() : tag;
-    }
-
-    public static String getTag(ServiceInstance instance) {
-        return instance.getMetadata().get(HEADER_TAG);
-    }
-
-    public static String getTag(Environment environment) {
-        String tag = environment.getProperty(EnvProperties.TAG_KEY);
-        // 如果请求的是 "${HOSTNAME}",则解析成对应的本地主机名
-        // 目的:特殊逻辑,解决 IDEA Rest Client 不支持环境变量的读取,所以就服务器来做
-        return Objects.equals(tag, HOST_NAME_VALUE) ? getHostName() : tag;
-    }
-
-    public static void setTag(RequestTemplate requestTemplate, String tag) {
-        requestTemplate.header(HEADER_TAG, tag);
-    }
-
-    /**
-     * 获得 hostname 主机名
-     *
-     * @return 主机名
-     */
-    @SneakyThrows
-    public static String getHostName() {
-        return InetAddress.getLocalHost().getHostName();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/web/EnvWebFilter.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/web/EnvWebFilter.java
deleted file mode 100644
index 9d1912f..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/core/web/EnvWebFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.iailab.framework.env.core.web;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.env.core.context.EnvContextHolder;
-import com.iailab.framework.env.core.util.EnvUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * 环境的 {@link javax.servlet.Filter} 实现类
- * 当有 tag 请求头时,设置到 {@link EnvContextHolder} 的标签上下文
- *
- * @author iailab
- */
-public class EnvWebFilter extends OncePerRequestFilter {
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        // 如果没有 tag,则走默认的流程
-        String tag = EnvUtils.getTag(request);
-        if (StrUtil.isEmpty(tag)) {
-            chain.doFilter(request, response);
-            return;
-        }
-
-        // 如果有 tag,则设置到上下文
-        EnvContextHolder.setTag(tag);
-        try {
-            chain.doFilter(request, response);
-        } finally {
-            EnvContextHolder.removeTag();
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/package-info.java b/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/package-info.java
deleted file mode 100644
index cf90d7c..0000000
--- a/iailab-framework/iailab-common-env/src/main/java/com/iailab/framework/env/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * 开发环境拓展,实现类似阿里的特性环境的能力
- * 1. https://segmentfault.com/a/1190000018022987
- *
- * @author iailab
- */
-package com.iailab.framework.env;
diff --git a/iailab-framework/iailab-common-env/src/main/resources/META-INF/spring.factories b/iailab-framework/iailab-common-env/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index e7a9ffe..0000000
--- a/iailab-framework/iailab-common-env/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.env.EnvironmentPostProcessor=\
-    com.iailab.framework.env.config.EnvEnvironmentPostProcessor
diff --git a/iailab-framework/iailab-common-env/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-env/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index f727275..0000000
--- a/iailab-framework/iailab-common-env/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.iailab.framework.env.config.IailabEnvWebAutoConfiguration
-com.iailab.framework.env.config.IailabEnvRpcAutoConfiguration
diff --git a/iailab-framework/iailab-common-excel/pom.xml b/iailab-framework/iailab-common-excel/pom.xml
deleted file mode 100644
index a069490..0000000
--- a/iailab-framework/iailab-common-excel/pom.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-excel</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>Excel 拓展</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Spring 核心 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-        </dependency>
-
-        <!-- RPC 远程调用相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-rpc</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- 业务组件 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-module-system-api</artifactId> <!-- 需要使用它,进行 Dict 的查询 -->
-            <version>${revision}</version>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有 ExcelUtils 使用 -->
-        </dependency>
-
-        <dependency>
-            <groupId>jakarta.servlet</groupId>
-            <artifactId>jakarta.servlet-api</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有 ExcelUtils 使用 -->
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>easyexcel</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-biz-ip</artifactId>
-            <optional>true</optional> <!-- 设置为 optional,只有在 AreaConvert 的时候使用 -->
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/config/IailabDictAutoConfiguration.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/config/IailabDictAutoConfiguration.java
deleted file mode 100644
index 9f1ed42..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/config/IailabDictAutoConfiguration.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.iailab.framework.dict.config;
-
-import com.iailab.framework.dict.core.DictFrameworkUtils;
-import com.iailab.module.system.api.dict.DictDataApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-
-@AutoConfiguration
-public class IailabDictAutoConfiguration {
-
-    @Bean
-    @SuppressWarnings("InstantiationOfUtilityClass")
-    public DictFrameworkUtils dictUtils(DictDataApi dictDataApi) {
-        DictFrameworkUtils.init(dictDataApi);
-        return new DictFrameworkUtils();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/config/IailabDictRpcAutoConfiguration.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/config/IailabDictRpcAutoConfiguration.java
deleted file mode 100644
index aff4b46..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/config/IailabDictRpcAutoConfiguration.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.iailab.framework.dict.config;
-
-import com.iailab.module.system.api.dict.DictDataApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.cloud.openfeign.EnableFeignClients;
-
-/**
- * 字典用到 Feign 的配置项
- *
- * @author iailab
- */
-@AutoConfiguration
-@EnableFeignClients(clients = DictDataApi.class) // 主要是引入相关的 API 服务
-public class IailabDictRpcAutoConfiguration {
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/core/DictFrameworkUtils.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/core/DictFrameworkUtils.java
deleted file mode 100644
index 307d8b6..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/core/DictFrameworkUtils.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.iailab.framework.dict.core;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.util.cache.CacheUtils;
-import com.iailab.module.system.api.dict.DictDataApi;
-import com.iailab.module.system.api.dict.dto.DictDataRespDTO;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-
-import java.time.Duration;
-import java.util.List;
-
-/**
- * 字典工具类
- *
- * @author iailab
- */
-@Slf4j
-public class DictFrameworkUtils {
-
-    private static DictDataApi dictDataApi;
-
-    private static final DictDataRespDTO DICT_DATA_NULL = new DictDataRespDTO();
-
-    // TODO @puhui999:GET_DICT_DATA_CACHE、GET_DICT_DATA_LIST_CACHE、PARSE_DICT_DATA_CACHE 这 3 个缓存是有点重叠,可以思考下,有没可能减少 1 个。微信讨论好私聊,再具体改哈
-    /**
-     * 针对 {@link #getDictDataLabel(String, String)} 的缓存
-     */
-    private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() {
-
-                @Override
-                public DictDataRespDTO load(KeyValue<String, String> key) {
-                    return ObjectUtil.defaultIfNull(dictDataApi.getDictData(key.getKey(), key.getValue()).getCheckedData(), DICT_DATA_NULL);
-                }
-
-            });
-
-    /**
-     * 针对 {@link #getDictDataLabelList(String)} 的缓存
-     */
-    private static final LoadingCache<String, List<String>> GET_DICT_DATA_LIST_CACHE = CacheUtils.buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<String, List<String>>() {
-
-                @Override
-                public List<String> load(String dictType) {
-                    return dictDataApi.getDictDataLabelList(dictType);
-                }
-
-            });
-
-    /**
-     * 针对 {@link #parseDictDataValue(String, String)} 的缓存
-     */
-    private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() {
-
-                @Override
-                public DictDataRespDTO load(KeyValue<String, String> key) {
-                    return ObjectUtil.defaultIfNull(dictDataApi.parseDictData(key.getKey(), key.getValue()).getCheckedData(), DICT_DATA_NULL);
-                }
-
-            });
-
-    public static void init(DictDataApi dictDataApi) {
-        DictFrameworkUtils.dictDataApi = dictDataApi;
-        log.info("[init][初始化 DictFrameworkUtils 成功]");
-    }
-
-    @SneakyThrows
-    public static String getDictDataLabel(String dictType, Integer value) {
-        return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, String.valueOf(value))).getLabel();
-    }
-
-    @SneakyThrows
-    public static String getDictDataLabel(String dictType, String value) {
-        return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel();
-    }
-
-    @SneakyThrows
-    public static List<String> getDictDataLabelList(String dictType) {
-        return GET_DICT_DATA_LIST_CACHE.get(dictType);
-    }
-
-    @SneakyThrows
-    public static String parseDictDataValue(String dictType, String label) {
-        return PARSE_DICT_DATA_CACHE.get(new KeyValue<>(dictType, label)).getValue();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/package-info.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/package-info.java
deleted file mode 100644
index b7a0386..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/dict/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 字典数据模块,提供 {@link com.iailab.framework.dict.core.DictFrameworkUtils} 工具类
- *
- * 通过将字典缓存在内存中,保证性能
- */
-package com.iailab.framework.dict;
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/annotations/DictFormat.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/annotations/DictFormat.java
deleted file mode 100644
index 9cd3996..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/annotations/DictFormat.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.excel.core.annotations;
-
-import java.lang.annotation.*;
-
-/**
- * 字典格式化
- *
- * 实现将字典数据的值,格式化成字典数据的标签
- */
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-public @interface DictFormat {
-
-    /**
-     * 例如说,SysDictTypeConstants、InfDictTypeConstants
-     *
-     * @return 字典类型
-     */
-    String value();
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/annotations/ExcelColumnSelect.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/annotations/ExcelColumnSelect.java
deleted file mode 100644
index 7956094..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/annotations/ExcelColumnSelect.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.excel.core.annotations;
-
-import java.lang.annotation.*;
-
-/**
- * 给 Excel 列添加下拉选择数据
- *
- * 其中 {@link #dictType()} 和 {@link #functionName()} 二选一
- *
- * @author HUIHUI
- */
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-public @interface ExcelColumnSelect {
-
-    /**
-     * @return 字典类型
-     */
-    String dictType() default "";
-
-    /**
-     * @return 获取下拉数据源的方法名称
-     */
-    String functionName() default "";
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/AreaConvert.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/AreaConvert.java
deleted file mode 100644
index 558c5f7..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/AreaConvert.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.excel.core.convert;
-
-import cn.hutool.core.convert.Convert;
-import com.iailab.framework.ip.core.Area;
-import com.iailab.framework.ip.core.utils.AreaUtils;
-import com.alibaba.excel.converters.Converter;
-import com.alibaba.excel.enums.CellDataTypeEnum;
-import com.alibaba.excel.metadata.GlobalConfiguration;
-import com.alibaba.excel.metadata.data.ReadCellData;
-import com.alibaba.excel.metadata.property.ExcelContentProperty;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Excel 数据地区转换器
- *
- * @author HUIHUI
- */
-@Slf4j
-public class AreaConvert implements Converter<Object> {
-
-    @Override
-    public Class<?> supportJavaTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public CellDataTypeEnum supportExcelTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty,
-                                    GlobalConfiguration globalConfiguration) {
-        // 解析地区编号
-        String label = readCellData.getStringValue();
-        Area area = AreaUtils.parseArea(label);
-        if (area == null) {
-            log.error("[convertToJavaData][label({}) 解析不掉]", label);
-            return null;
-        }
-        // 将 value 转换成对应的属性
-        Class<?> fieldClazz = contentProperty.getField().getType();
-        return Convert.convert(fieldClazz, area.getId());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/DictConvert.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/DictConvert.java
deleted file mode 100644
index 9b667f3..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/DictConvert.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.iailab.framework.excel.core.convert;
-
-import cn.hutool.core.convert.Convert;
-import com.iailab.framework.dict.core.DictFrameworkUtils;
-import com.iailab.framework.excel.core.annotations.DictFormat;
-import com.alibaba.excel.converters.Converter;
-import com.alibaba.excel.enums.CellDataTypeEnum;
-import com.alibaba.excel.metadata.GlobalConfiguration;
-import com.alibaba.excel.metadata.data.ReadCellData;
-import com.alibaba.excel.metadata.data.WriteCellData;
-import com.alibaba.excel.metadata.property.ExcelContentProperty;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * Excel 数据字典转换器
- *
- * @author iailab
- */
-@Slf4j
-public class DictConvert implements Converter<Object> {
-
-    @Override
-    public Class<?> supportJavaTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public CellDataTypeEnum supportExcelTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty,
-                                    GlobalConfiguration globalConfiguration) {
-        // 使用字典解析
-        String type = getType(contentProperty);
-        String label = readCellData.getStringValue();
-        String value = DictFrameworkUtils.parseDictDataValue(type, label);
-        if (value == null) {
-            log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label);
-            return null;
-        }
-        // 将 String 的 value 转换成对应的属性
-        Class<?> fieldClazz = contentProperty.getField().getType();
-        return Convert.convert(fieldClazz, value);
-    }
-
-    @Override
-    public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty,
-                                                    GlobalConfiguration globalConfiguration) {
-        // 空时,返回空
-        if (object == null) {
-            return new WriteCellData<>("");
-        }
-
-        // 使用字典格式化
-        String type = getType(contentProperty);
-        String value = String.valueOf(object);
-        String label = DictFrameworkUtils.getDictDataLabel(type, value);
-        if (label == null) {
-            log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);
-            return new WriteCellData<>("");
-        }
-        // 生成 Excel 小表格
-        return new WriteCellData<>(label);
-    }
-
-    private static String getType(ExcelContentProperty contentProperty) {
-        return contentProperty.getField().getAnnotation(DictFormat.class).value();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/JsonConvert.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/JsonConvert.java
deleted file mode 100644
index 5a29d08..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/JsonConvert.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.iailab.framework.excel.core.convert;
-
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.alibaba.excel.converters.Converter;
-import com.alibaba.excel.enums.CellDataTypeEnum;
-import com.alibaba.excel.metadata.GlobalConfiguration;
-import com.alibaba.excel.metadata.data.WriteCellData;
-import com.alibaba.excel.metadata.property.ExcelContentProperty;
-
-/**
- * Excel Json 转换器
- *
- * @author iailab
- */
-public class JsonConvert implements Converter<Object> {
-
-    @Override
-    public Class<?> supportJavaTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public CellDataTypeEnum supportExcelTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public WriteCellData<String> convertToExcelData(Object value, ExcelContentProperty contentProperty,
-                                                    GlobalConfiguration globalConfiguration) {
-        // 生成 Excel 小表格
-        return new WriteCellData<>(JsonUtils.toJsonString(value));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/MoneyConvert.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/MoneyConvert.java
deleted file mode 100644
index fce1e64..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/convert/MoneyConvert.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.framework.excel.core.convert;
-
-import com.alibaba.excel.converters.Converter;
-import com.alibaba.excel.enums.CellDataTypeEnum;
-import com.alibaba.excel.metadata.GlobalConfiguration;
-import com.alibaba.excel.metadata.data.WriteCellData;
-import com.alibaba.excel.metadata.property.ExcelContentProperty;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-
-/**
- * 金额转换器
- *
- * 金额单位:分
- *
- * @author iailab
- */
-public class MoneyConvert implements Converter<Integer> {
-
-    @Override
-    public Class<?> supportJavaTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public CellDataTypeEnum supportExcelTypeKey() {
-        throw new UnsupportedOperationException("暂不支持,也不需要");
-    }
-
-    @Override
-    public WriteCellData<String> convertToExcelData(Integer value, ExcelContentProperty contentProperty,
-                                                    GlobalConfiguration globalConfiguration) {
-        BigDecimal result = BigDecimal.valueOf(value)
-                .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
-        return new WriteCellData<>(result.toString());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/function/ExcelColumnSelectFunction.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/function/ExcelColumnSelectFunction.java
deleted file mode 100644
index a817d4b..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/function/ExcelColumnSelectFunction.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.excel.core.function;
-
-import java.util.List;
-
-/**
- * Excel 列下拉数据源获取接口
- *
- * 为什么不直接解析字典还搞个接口?考虑到有的下拉数据不是从字典中获取的所有需要做一个兼容
-
- * @author HUIHUI
- */
-public interface ExcelColumnSelectFunction {
-
-    /**
-     * 获得方法名称
-     *
-     * @return 方法名称
-     */
-    String getName();
-
-    /**
-     * 获得列下拉数据源
-     *
-     * @return 下拉数据源
-     */
-    List<String> getOptions();
-
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/handler/SelectSheetWriteHandler.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/handler/SelectSheetWriteHandler.java
deleted file mode 100644
index 9e5e3df..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/handler/SelectSheetWriteHandler.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.iailab.framework.excel.core.handler;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.extra.spring.SpringUtil;
-import cn.hutool.poi.excel.ExcelUtil;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.alibaba.excel.write.handler.SheetWriteHandler;
-import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
-import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.dict.core.DictFrameworkUtils;
-import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
-import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.hssf.usermodel.HSSFDataValidation;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddressList;
-
-import java.lang.reflect.Field;
-import java.util.*;
-
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
-
-/**
- * 基于固定 sheet 实现下拉框
- *
- * @author HUIHUI
- */
-@Slf4j
-public class SelectSheetWriteHandler implements SheetWriteHandler {
-
-    /**
-     * 数据起始行从 0 开始
-     * 约定:本项目第一行有标题所以从 1 开始如果您的 Excel 有多行标题请自行更改
-     */
-    public static final int FIRST_ROW = 1;
-    /**
-     * 下拉列需要创建下拉框的行数,默认两千行如需更多请自行调整
-     */
-    public static final int LAST_ROW = 2000;
-
-    private static final String DICT_SHEET_NAME = "字典sheet";
-
-    /**
-     * key: 列 value: 下拉数据源
-     */
-    private final Map<Integer, List<String>> selectMap = new HashMap<>();
-
-    private static Boolean ifSetSelect;
-
-    public SelectSheetWriteHandler(Class<?> head, Boolean selectFlag) {
-        ifSetSelect = selectFlag;
-        // 加载下拉数据获取接口
-        Map<String, ExcelColumnSelectFunction> beansMap = SpringUtil.getBeanFactory().getBeansOfType(ExcelColumnSelectFunction.class);
-        if (MapUtil.isEmpty(beansMap)) {
-            return;
-        }
-        List<Field> fields = new ArrayList<>();
-        for (Class<?> c = head; c != null; c = c.getSuperclass()) {
-            Collections.addAll(fields, c.getDeclaredFields());
-        }
-        // 解析下拉数据
-        int colIndex = 0;
-        for (Field field : fields) {
-            if (field.isAnnotationPresent(ExcelColumnSelect.class)) {
-                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
-                if (excelProperty != null && excelProperty.index() != -1) {
-                    getSelectDataList(excelProperty.index(), field);
-                }else{
-                    getSelectDataList(colIndex, field);
-                }
-            }
-            colIndex++;
-        }
-    }
-
-    /**
-     * 获得下拉数据,并添加到 {@link #selectMap} 中
-     *
-     * @param colIndex 列索引
-     * @param field    字段
-     */
-    private void getSelectDataList(int colIndex, Field field) {
-        ExcelColumnSelect columnSelect = field.getAnnotation(ExcelColumnSelect.class);
-        String dictType = columnSelect.dictType();
-        String functionName = columnSelect.functionName();
-        Assert.isTrue(ObjectUtil.isNotEmpty(dictType) || ObjectUtil.isNotEmpty(functionName),
-                "Field({}) 的 @ExcelColumnSelect 注解,dictType 和 functionName 不能同时为空", field.getName());
-
-        // 情况一:使用 dictType 获得下拉数据
-        if (StrUtil.isNotEmpty(dictType)) { // 情况一: 字典数据 (默认)
-            selectMap.put(colIndex, DictFrameworkUtils.getDictDataLabelList(dictType));
-            return;
-        }
-
-        // 情况二:使用 functionName 获得下拉数据
-        Map<String, ExcelColumnSelectFunction> functionMap = SpringUtil.getApplicationContext().getBeansOfType(ExcelColumnSelectFunction.class);
-        ExcelColumnSelectFunction function = CollUtil.findOne(functionMap.values(), item -> item.getName().equals(functionName));
-        Assert.notNull(function, "未找到对应的 function({})", functionName);
-        selectMap.put(colIndex, function.getOptions());
-    }
-
-    @Override
-    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
-        if (CollUtil.isEmpty(selectMap)) {
-            return;
-        }
-        // 1. 获取相应操作对象
-        DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper(); // 需要设置下拉框的 sheet 页的数据验证助手
-        Workbook workbook = writeWorkbookHolder.getWorkbook(); // 获得工作簿
-        List<KeyValue<Integer, List<String>>> keyValues = convertList(selectMap.entrySet(), entry -> new KeyValue<>(entry.getKey(), entry.getValue()));
-        keyValues.sort(Comparator.comparing(item -> item.getValue().size())); // 升序不然创建下拉会报错
-        if (ifSetSelect){
-            for (KeyValue<Integer, List<String>> keyValue : keyValues) {
-                /*起始行、终止行、起始列、终止列  起始行为1即表示表头不设置**/
-                CellRangeAddressList addressList = new CellRangeAddressList(FIRST_ROW, LAST_ROW, keyValue.getKey(), keyValue.getKey());
-                /*设置下拉框数据**/
-                DataValidationConstraint constraint = helper.createExplicitListConstraint(keyValue.getValue().toArray(new String[0]));
-                DataValidation dataValidation = helper.createValidation(constraint, addressList);
-                if (dataValidation instanceof HSSFDataValidation) {
-                    dataValidation.setSuppressDropDownArrow(false);
-                } else {
-                    dataValidation.setSuppressDropDownArrow(true);
-                    dataValidation.setShowErrorBox(true);
-                }
-                // 2.2 阻止输入非下拉框的值
-                dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
-                dataValidation.createErrorBox("提示", "此值不存在于下拉选择中!");
-                writeSheetHolder.getSheet().addValidationData(dataValidation);
-            }
-        }else{
-            // 2. 创建数据字典的 sheet 页
-            Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME);
-            for (KeyValue<Integer, List<String>> keyValue : keyValues) {
-                int rowLength = keyValue.getValue().size();
-                // 2.1 设置字典 sheet 页的值,每一列一部字典项
-                for (int i = 0; i < rowLength; i++) {
-                    Row row = dictSheet.getRow(i);
-                    if (row == null) {
-                        row = dictSheet.createRow(i);
-                    }
-                    row.createCell(keyValue.getKey()).setCellValue(keyValue.getValue().get(i));
-                }
-                // 2.2 设置单元格下拉选择
-                setColumnSelect(writeSheetHolder, workbook, helper, keyValue);
-            }
-        }
-    }
-
-    /**
-     * 设置单元格下拉选择
-     */
-    private static void setColumnSelect(WriteSheetHolder writeSheetHolder, Workbook workbook, DataValidationHelper helper,
-                                        KeyValue<Integer, List<String>> keyValue) {
-        // 1.1 创建可被其他单元格引用的名称
-        Name name = workbook.createName();
-        String excelColumn = ExcelUtil.indexToColName(keyValue.getKey());
-        // 1.2 下拉框数据来源 eg:字典sheet!$B1:$B2
-        String refers = DICT_SHEET_NAME + "!$" + excelColumn + "$1:$" + excelColumn + "$" + keyValue.getValue().size();
-        name.setNameName("dict" + keyValue.getKey()); // 设置名称的名字
-        name.setRefersToFormula(refers); // 设置公式
-
-        // 2.1 设置约束
-        DataValidationConstraint constraint = helper.createFormulaListConstraint("dict" + keyValue.getKey()); // 设置引用约束
-        // 设置下拉单元格的首行、末行、首列、末列
-        CellRangeAddressList rangeAddressList = new CellRangeAddressList(FIRST_ROW, LAST_ROW,
-                keyValue.getKey(), keyValue.getKey());
-        DataValidation validation = helper.createValidation(constraint, rangeAddressList);
-        if (validation instanceof HSSFDataValidation) {
-            validation.setSuppressDropDownArrow(false);
-        } else {
-            validation.setSuppressDropDownArrow(true);
-            validation.setShowErrorBox(true);
-        }
-        // 2.2 阻止输入非下拉框的值
-        validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
-        validation.createErrorBox("提示", "此值不存在于下拉选择中!");
-        // 2.3 添加下拉框约束
-        writeSheetHolder.getSheet().addValidationData(validation);
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/util/ExcelUtils.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/util/ExcelUtils.java
deleted file mode 100644
index f16434e..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/util/ExcelUtils.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.iailab.framework.excel.core.util;
-
-import com.iailab.framework.excel.core.handler.SelectSheetWriteHandler;
-import com.alibaba.excel.EasyExcel;
-import com.alibaba.excel.converters.longconverter.LongStringConverter;
-import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-/**
- * Excel 工具类
- *
- * @author iailab
- */
-public class ExcelUtils {
-
-    /**
-     * 将列表以 Excel 响应给前端
-     *
-     * @param response  响应
-     * @param filename  文件名
-     * @param sheetName Excel sheet 名
-     * @param head      Excel head 头
-     * @param data      数据列表哦
-     * @param <T>       泛型,保证 head 和 data 类型的一致性
-     * @throws IOException 写入失败的情况
-     */
-    public static <T> void write(HttpServletResponse response, String filename, String sheetName,
-                                 Class<T> head, List<T> data) throws IOException {
-        // 输出 Excel
-        EasyExcel.write(response.getOutputStream(), head)
-                .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
-                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
-                .registerWriteHandler(new SelectSheetWriteHandler(head,false)) // 基于固定 sheet 实现下拉框
-                .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
-                .sheet(sheetName).doWrite(data);
-        // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
-        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
-        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
-    }
-
-    public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
-        return EasyExcel.read(file.getInputStream(), head, null)
-                .autoCloseStream(false)  // 不要自动关闭,交给 Servlet 自己处理
-                .doReadAllSync();
-    }
-
-    public static <T> void write(HttpServletResponse response, String filename, String sheetName,
-                                 Class<T> head, List<T> data, boolean selectFlag) throws IOException {
-        // 输出 Excel
-        EasyExcel.write(response.getOutputStream(), head)
-                .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
-                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
-                .registerWriteHandler(new SelectSheetWriteHandler(head,selectFlag)) // 基于固定 sheet 实现下拉框
-                .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
-                .sheet(sheetName).doWrite(data);
-        // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
-        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
-        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
-    }
-}
diff --git a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/package-info.java b/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/package-info.java
deleted file mode 100644
index 21caa19..0000000
--- a/iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 基于 EasyExcel 实现 Excel 相关的操作
- */
-package com.iailab.framework.excel;
diff --git a/iailab-framework/iailab-common-excel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-excel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 889b89f..0000000
--- a/iailab-framework/iailab-common-excel/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.iailab.framework.dict.config.IailabDictRpcAutoConfiguration
-com.iailab.framework.dict.config.IailabDictAutoConfiguration
diff --git a/iailab-framework/iailab-common-excel/src/test/java/com/iailab/framework/dict/core/util/DictFrameworkUtilsTest.java b/iailab-framework/iailab-common-excel/src/test/java/com/iailab/framework/dict/core/util/DictFrameworkUtilsTest.java
deleted file mode 100644
index 157eae1..0000000
--- a/iailab-framework/iailab-common-excel/src/test/java/com/iailab/framework/dict/core/util/DictFrameworkUtilsTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.iailab.framework.dict.core.util;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.dict.core.DictFrameworkUtils;
-import com.iailab.framework.test.core.ut.BaseMockitoUnitTest;
-import com.iailab.module.system.api.dict.DictDataApi;
-import com.iailab.module.system.api.dict.dto.DictDataRespDTO;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-import static com.iailab.framework.test.core.util.RandomUtils.randomPojo;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.when;
-
-/**
- * {@link DictFrameworkUtils} 的单元测试
- */
-public class DictFrameworkUtilsTest extends BaseMockitoUnitTest {
-
-    @Mock
-    private DictDataApi dictDataApi;
-
-    @BeforeEach
-    public void setUp() {
-        DictFrameworkUtils.init(dictDataApi);
-    }
-
-    @Test
-    public void testGetDictDataLabel() {
-        // mock 数据
-        DictDataRespDTO dataRespDTO = randomPojo(DictDataRespDTO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        // mock 方法
-        when(dictDataApi.getDictData(dataRespDTO.getDictType(), dataRespDTO.getValue())).thenReturn(success(dataRespDTO));
-
-        // 断言返回值
-        assertEquals(dataRespDTO.getLabel(), DictFrameworkUtils.getDictDataLabel(dataRespDTO.getDictType(), dataRespDTO.getValue()));
-    }
-
-    @Test
-    public void testParseDictDataValue() {
-        // mock 数据
-        DictDataRespDTO resp = randomPojo(DictDataRespDTO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
-        // mock 方法
-        when(dictDataApi.parseDictData(resp.getDictType(), resp.getLabel())).thenReturn(success(resp));
-        // 断言返回值
-        assertEquals(resp.getValue(), DictFrameworkUtils.parseDictDataValue(resp.getDictType(), resp.getLabel()));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-job/pom.xml b/iailab-framework/iailab-common-job/pom.xml
deleted file mode 100644
index 38dd07a..0000000
--- a/iailab-framework/iailab-common-job/pom.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-job</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>任务拓展,基于 XXL-Job 实现</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Spring 核心 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Job 相关 -->
-        <dependency>
-            <groupId>com.xuxueli</groupId>
-            <artifactId>xxl-job-core</artifactId>
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>jakarta.validation</groupId>
-            <artifactId>jakarta.validation-api</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/IailabAsyncAutoConfiguration.java b/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/IailabAsyncAutoConfiguration.java
deleted file mode 100644
index 58c2947..0000000
--- a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/IailabAsyncAutoConfiguration.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.quartz.config;
-
-import com.alibaba.ttl.TtlRunnable;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableAsync;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-
-/**
- * 异步任务 Configuration
- */
-@AutoConfiguration
-@EnableAsync
-public class IailabAsyncAutoConfiguration {
-
-    @Bean
-    public BeanPostProcessor threadPoolTaskExecutorBeanPostProcessor() {
-        return new BeanPostProcessor() {
-
-            @Override
-            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
-                if (!(bean instanceof ThreadPoolTaskExecutor)) {
-                    return bean;
-                }
-                // 修改提交的任务,接入 TransmittableThreadLocal
-                ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean;
-                executor.setTaskDecorator(TtlRunnable::get);
-                return executor;
-            }
-
-        };
-    }
-
-}
diff --git a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/IailabXxlJobAutoConfiguration.java b/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/IailabXxlJobAutoConfiguration.java
deleted file mode 100644
index 297ce1f..0000000
--- a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/IailabXxlJobAutoConfiguration.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.iailab.framework.quartz.config;
-
-import com.xxl.job.core.executor.XxlJobExecutor;
-import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableScheduling;
-
-/**
- * XXL-Job 自动配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-@ConditionalOnClass(XxlJobSpringExecutor.class)
-@ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true", matchIfMissing = true)
-@EnableConfigurationProperties({XxlJobProperties.class})
-@EnableScheduling // 开启 Spring 自带的定时任务
-@Slf4j
-public class IailabXxlJobAutoConfiguration {
-
-    @Bean
-    @ConditionalOnMissingBean
-    public XxlJobExecutor xxlJobExecutor(XxlJobProperties properties) {
-        log.info("[xxlJobExecutor][初始化 XXL-Job 执行器的配置]");
-        XxlJobProperties.AdminProperties admin = properties.getAdmin();
-        XxlJobProperties.ExecutorProperties executor = properties.getExecutor();
-
-        // 初始化执行器
-        XxlJobExecutor xxlJobExecutor = new XxlJobSpringExecutor();
-        xxlJobExecutor.setIp(executor.getIp());
-        xxlJobExecutor.setPort(executor.getPort());
-        xxlJobExecutor.setAppname(executor.getAppName());
-        xxlJobExecutor.setLogPath(executor.getLogPath());
-        xxlJobExecutor.setLogRetentionDays(executor.getLogRetentionDays());
-        xxlJobExecutor.setAdminAddresses(admin.getAddresses());
-        xxlJobExecutor.setAccessToken(properties.getAccessToken());
-        return xxlJobExecutor;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/XxlJobProperties.java b/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/XxlJobProperties.java
deleted file mode 100644
index 5d09c7b..0000000
--- a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/config/XxlJobProperties.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.iailab.framework.quartz.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-/**
- * XXL-Job 配置类
- */
-@ConfigurationProperties("xxl.job")
-@Validated
-@Data
-public class XxlJobProperties {
-
-    /**
-     * 是否开启,默认为 true 关闭
-     */
-    private Boolean enabled = true;
-    /**
-     * 访问令牌
-     */
-    private String accessToken;
-    /**
-     * 控制器配置
-     */
-    @NotNull(message = "控制器配置不能为空")
-    private AdminProperties admin;
-    /**
-     * 执行器配置
-     */
-    @NotNull(message = "执行器配置不能为空")
-    private ExecutorProperties executor;
-
-    /**
-     * XXL-Job 调度器配置类
-     */
-    @Data
-    @Valid
-    public static class AdminProperties {
-
-        /**
-         * 调度器地址
-         */
-        @NotEmpty(message = "调度器地址不能为空")
-        private String addresses;
-
-    }
-
-    /**
-     * XXL-Job 执行器配置类
-     */
-    @Data
-    @Valid
-    public static class ExecutorProperties {
-
-        /**
-         * 默认端口
-         *
-         * 这里使用 -1 表示随机
-         */
-        private static final Integer PORT_DEFAULT = -1;
-
-        /**
-         * 默认日志保留天数
-         *
-         * 如果想永久保留,则设置为 -1
-         */
-        private static final Integer LOG_RETENTION_DAYS_DEFAULT = 30;
-
-        /**
-         * 应用名
-         */
-        @NotEmpty(message = "应用名不能为空")
-        private String appName;
-        /**
-         * 执行器的 IP
-         */
-        private String ip;
-        /**
-         * 执行器的 Port
-         */
-        private Integer port = PORT_DEFAULT;
-        /**
-         * 日志地址
-         */
-        @NotEmpty(message = "日志地址不能为空")
-        private String logPath;
-        /**
-         * 日志保留天数
-         */
-        private Integer logRetentionDays = LOG_RETENTION_DAYS_DEFAULT;
-
-    }
-
-}
diff --git a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/package-info.java b/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/package-info.java
deleted file mode 100644
index 38ff695..0000000
--- a/iailab-framework/iailab-common-job/src/main/java/com/iailab/framework/quartz/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * 1. 定时任务,基于 XXL-Job 实现。
- * 2. 异步任务,采用 Spring Async 异步执行。
- */
-package com.iailab.framework.quartz;
diff --git a/iailab-framework/iailab-common-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index f76be21..0000000
--- a/iailab-framework/iailab-common-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.iailab.framework.quartz.config.IailabXxlJobAutoConfiguration
-com.iailab.framework.quartz.config.IailabAsyncAutoConfiguration
diff --git a/iailab-framework/iailab-common-monitor/pom.xml b/iailab-framework/iailab-common-monitor/pom.xml
deleted file mode 100644
index 2746113..0000000
--- a/iailab-framework/iailab-common-monitor/pom.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-monitor</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>服务监控,提供链路追踪、日志服务、指标收集等等功能</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Spring 核心 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有 TraceFilter 使用 -->
-        </dependency>
-
-        <dependency>
-            <groupId>jakarta.servlet</groupId>
-            <artifactId>jakarta.servlet-api</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有 TraceFilter 使用 -->
-        </dependency>
-
-        <!-- 监控相关 -->
-        <dependency>
-            <groupId>io.opentracing</groupId>
-            <artifactId>opentracing-util</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.skywalking</groupId>
-            <artifactId>apm-toolkit-trace</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.skywalking</groupId>
-            <artifactId>apm-toolkit-logback-1.x</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.skywalking</groupId>
-            <artifactId>apm-toolkit-opentracing</artifactId>
-        </dependency>
-
-        <!-- Micrometer 对 Prometheus 的支持 -->
-        <dependency>
-            <groupId>io.micrometer</groupId>
-            <artifactId>micrometer-registry-prometheus</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>de.codecentric</groupId>
-            <artifactId>spring-boot-admin-starter-client</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/IailabMetricsAutoConfiguration.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/IailabMetricsAutoConfiguration.java
deleted file mode 100644
index 9d46110..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/IailabMetricsAutoConfiguration.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.tracer.config;
-
-import io.micrometer.core.instrument.MeterRegistry;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Metrics 配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-@ConditionalOnClass({MeterRegistryCustomizer.class})
-@ConditionalOnProperty(prefix = "iailab.metrics", value = "enable", matchIfMissing = true) // 允许使用 iailab.metrics.enable=false 禁用 Metrics
-public class IailabMetricsAutoConfiguration {
-
-    @Bean
-    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags(
-            @Value("${spring.application.name}") String applicationName) {
-        return registry -> registry.config().commonTags("application", applicationName);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/IailabTracerAutoConfiguration.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/IailabTracerAutoConfiguration.java
deleted file mode 100644
index 48072c5..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/IailabTracerAutoConfiguration.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.iailab.framework.tracer.config;
-
-import com.iailab.framework.common.enums.WebFilterOrderEnum;
-import com.iailab.framework.tracer.core.aop.BizTraceAspect;
-import com.iailab.framework.tracer.core.filter.TraceFilter;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-
-/**
- * Tracer 配置类
- *
- * @author mashu
- */
-@AutoConfiguration
-@ConditionalOnClass({BizTraceAspect.class})
-@EnableConfigurationProperties(TracerProperties.class)
-@ConditionalOnProperty(prefix = "iailab.tracer", value = "enable", matchIfMissing = true)
-public class IailabTracerAutoConfiguration {
-
-    // TODO @iailab:重要。目前 opentracing 版本存在冲突,要么保证 skywalking,要么保证阿里云短信 sdk
-//    @Bean
-//    public TracerProperties bizTracerProperties() {
-//        return new TracerProperties();
-//    }
-//
-//    @Bean
-//    public BizTraceAspect bizTracingAop() {
-//        return new BizTraceAspect(tracer());
-//    }
-//
-//    @Bean
-//    public Tracer tracer() {
-//        // 创建 SkywalkingTracer 对象
-//        SkywalkingTracer tracer = new SkywalkingTracer();
-//        // 设置为 GlobalTracer 的追踪器
-//        GlobalTracer.register(tracer);
-//        return tracer;
-//    }
-
-    /**
-     * 创建 TraceFilter 过滤器,响应 header 设置 traceId
-     */
-    @Bean
-    public FilterRegistrationBean<TraceFilter> traceFilter() {
-        FilterRegistrationBean<TraceFilter> registrationBean = new FilterRegistrationBean<>();
-        registrationBean.setFilter(new TraceFilter());
-        registrationBean.setOrder(WebFilterOrderEnum.TRACE_FILTER);
-        return registrationBean;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/TracerProperties.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/TracerProperties.java
deleted file mode 100644
index a779e16..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/config/TracerProperties.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.iailab.framework.tracer.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * BizTracer配置类
- *
- * @author 麻薯
- */
-@ConfigurationProperties("iailab.tracer")
-@Data
-public class TracerProperties {
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/annotation/BizTrace.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/annotation/BizTrace.java
deleted file mode 100644
index 074bb18..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/annotation/BizTrace.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.framework.tracer.core.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * 打印业务编号 / 业务类型注解
- *
- * 使用时,需要设置 SkyWalking OAP Server 的 application.yaml 配置文件,修改 SW_SEARCHABLE_TAG_KEYS 配置项,
- * 增加 biz.type 和 biz.id 两值,然后重启 SkyWalking OAP Server 服务器。
- *
- * @author 麻薯
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-public @interface BizTrace {
-
-    /**
-     * 业务编号 tag 名
-     */
-    String ID_TAG = "biz.id";
-    /**
-     * 业务类型 tag 名
-     */
-    String TYPE_TAG = "biz.type";
-
-    /**
-     * @return 操作名
-     */
-    String operationName() default "";
-
-    /**
-     * @return 业务编号
-     */
-    String id();
-
-    /**
-     * @return 业务类型
-     */
-    String type();
-
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/aop/BizTraceAspect.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/aop/BizTraceAspect.java
deleted file mode 100644
index 954e933..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/aop/BizTraceAspect.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.iailab.framework.tracer.core.aop;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.tracer.core.annotation.BizTrace;
-import com.iailab.framework.common.util.spring.SpringExpressionUtils;
-import com.iailab.framework.tracer.core.util.TracerFrameworkUtils;
-import io.opentracing.Span;
-import io.opentracing.Tracer;
-import io.opentracing.tag.Tags;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-
-import java.util.Map;
-
-import static java.util.Arrays.asList;
-
-/**
- * {@link BizTrace} 切面,记录业务链路
- *
- * @author mashu
- */
-@Aspect
-@AllArgsConstructor
-@Slf4j
-public class BizTraceAspect {
-
-    private static final String BIZ_OPERATION_NAME_PREFIX = "Biz/";
-
-    private final Tracer tracer;
-
-    @Around(value = "@annotation(trace)")
-    public Object around(ProceedingJoinPoint joinPoint, BizTrace trace) throws Throwable {
-        // 创建 span
-        String operationName = getOperationName(joinPoint, trace);
-        Span span = tracer.buildSpan(operationName)
-                .withTag(Tags.COMPONENT.getKey(), "biz")
-                .start();
-        try {
-            // 执行原有方法
-            return joinPoint.proceed();
-        } catch (Throwable throwable) {
-            TracerFrameworkUtils.onError(throwable, span);
-            throw throwable;
-        } finally {
-            // 设置 Span 的 biz 属性
-            setBizTag(span, joinPoint, trace);
-            // 完成 Span
-            span.finish();
-        }
-    }
-
-    private String getOperationName(ProceedingJoinPoint joinPoint, BizTrace trace) {
-        // 自定义操作名
-        if (StrUtil.isNotEmpty(trace.operationName())) {
-            return BIZ_OPERATION_NAME_PREFIX + trace.operationName();
-        }
-        // 默认操作名,使用方法名
-        return BIZ_OPERATION_NAME_PREFIX
-                + joinPoint.getSignature().getDeclaringType().getSimpleName()
-                + "/" + joinPoint.getSignature().getName();
-    }
-
-    private void setBizTag(Span span, ProceedingJoinPoint joinPoint, BizTrace trace) {
-        try {
-            Map<String, Object> result = SpringExpressionUtils.parseExpressions(joinPoint, asList(trace.type(), trace.id()));
-            span.setTag(BizTrace.TYPE_TAG, MapUtil.getStr(result, trace.type()));
-            span.setTag(BizTrace.ID_TAG, MapUtil.getStr(result, trace.id()));
-        } catch (Exception ex) {
-            log.error("[setBizTag][解析 bizType 与 bizId 发生异常]", ex);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/filter/TraceFilter.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/filter/TraceFilter.java
deleted file mode 100644
index 75f943c..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/filter/TraceFilter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.iailab.framework.tracer.core.filter;
-
-import com.iailab.framework.common.util.monitor.TracerUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * Trace 过滤器,打印 traceId 到 header 中返回
- *
- * @author iailab
- */
-public class TraceFilter extends OncePerRequestFilter {
-
-    /**
-     * Header 名 - 链路追踪编号
-     */
-    private static final String HEADER_NAME_TRACE_ID = "trace-id";
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws IOException, ServletException {
-        // 设置响应 traceId
-        response.addHeader(HEADER_NAME_TRACE_ID, TracerUtils.getTraceId());
-        // 继续过滤
-        chain.doFilter(request, response);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/util/TracerFrameworkUtils.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/util/TracerFrameworkUtils.java
deleted file mode 100644
index 0e08f91..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/core/util/TracerFrameworkUtils.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.tracer.core.util;
-
-import io.opentracing.Span;
-import io.opentracing.tag.Tags;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 链路追踪 Util
- *
- * @author iailab
- */
-public class TracerFrameworkUtils {
-
-    /**
-     * 将异常记录到 Span 中,参考自 com.aliyuncs.utils.TraceUtils
-     *
-     * @param throwable 异常
-     * @param span Span
-     */
-    public static void onError(Throwable throwable, Span span) {
-        Tags.ERROR.set(span, Boolean.TRUE);
-        if (throwable != null) {
-            span.log(errorLogs(throwable));
-        }
-    }
-
-    private static Map<String, Object> errorLogs(Throwable throwable) {
-        Map<String, Object> errorLogs = new HashMap<String, Object>(10);
-        errorLogs.put("event", Tags.ERROR.getKey());
-        errorLogs.put("error.object", throwable);
-        errorLogs.put("error.kind", throwable.getClass().getName());
-        String message = throwable.getCause() != null ? throwable.getCause().getMessage() : throwable.getMessage();
-        if (message != null) {
-            errorLogs.put("message", message);
-        }
-        StringWriter sw = new StringWriter();
-        throwable.printStackTrace(new PrintWriter(sw));
-        errorLogs.put("stack", sw.toString());
-        return errorLogs;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/package-info.java b/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/package-info.java
deleted file mode 100644
index 681acc6..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/java/com/iailab/framework/tracer/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 使用 SkyWalking 组件,作为链路追踪、日志中心。
- *
- * @author iailab
- */
-package com.iailab.framework.tracer;
diff --git a/iailab-framework/iailab-common-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index d5e538e..0000000
--- a/iailab-framework/iailab-common-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.iailab.framework.tracer.config.IailabTracerAutoConfiguration
-com.iailab.framework.tracer.config.IailabMetricsAutoConfiguration
diff --git a/iailab-framework/iailab-common-mq/pom.xml b/iailab-framework/iailab-common-mq/pom.xml
deleted file mode 100644
index 29b9b2b..0000000
--- a/iailab-framework/iailab-common-mq/pom.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-mq</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-redis</artifactId>
-        </dependency>
-
-        <!-- 消息队列相关 -->
-        <dependency>
-            <groupId>org.springframework.kafka</groupId>
-            <artifactId>spring-kafka</artifactId>
-<!--            <optional>true</optional>-->
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.amqp</groupId>
-            <artifactId>spring-rabbit</artifactId>
-<!--            <optional>true</optional>-->
-        </dependency>
-        <dependency>
-            <groupId>org.apache.rocketmq</groupId>
-            <artifactId>rocketmq-spring-boot-starter</artifactId>
-<!--            <optional>true</optional>-->
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/common/RoutingConstant.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/common/RoutingConstant.java
deleted file mode 100644
index 47d1c14..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/common/RoutingConstant.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.mq.common;
-
-/**
- *
- *
- * @author PanZhibao
- * @Description
- * @createTime 2024年11月05日
- */
-public interface RoutingConstant {
-
-    String Iailab_Data_PointCollectFinish = "Iailab.Data.PointCollectFinish";
-
-    // 摄像头通配路由
-    String Iailab_Data_Image = "Iailab.Data.Image.*";
-
-    // 大华摄像头路由
-    String Iailab_Data_Image_Dahua = "Iailab.Data.Image.Dahua";
-
-    // 海康摄像头路由
-    String Iailab_Data_Image_Hikvision = "Iailab.Data.Image.Hikvision";
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/package-info.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/package-info.java
deleted file mode 100644
index 74fea2a..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 消息队列,支持 Redis、RocketMQ、RabbitMQ、Kafka 四种
- */
-package com.iailab.framework.mq;
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/config/IailabRabbitMQAutoConfiguration.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/config/IailabRabbitMQAutoConfiguration.java
deleted file mode 100644
index 2efeb3b..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/config/IailabRabbitMQAutoConfiguration.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.mq.rabbitmq.config;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
-import org.springframework.amqp.support.converter.MessageConverter;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.context.annotation.Bean;
-
-/**
- * RabbitMQ 消息队列配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-@Slf4j
-@ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
-public class IailabRabbitMQAutoConfiguration {
-
-    /**
-     * Jackson2JsonMessageConverter Bean:使用 jackson 序列化消息
-     */
-    @Bean
-    public MessageConverter createMessageConverter() {
-        return new Jackson2JsonMessageConverter();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/core/package-info.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/core/package-info.java
deleted file mode 100644
index 1340868..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/core/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 占位符,无特殊逻辑
- */
-package com.iailab.framework.mq.rabbitmq.core;
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/package-info.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/package-info.java
deleted file mode 100644
index 1582bcb..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/rabbitmq/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 消息队列,基于 RabbitMQ 提供
- */
-package com.iailab.framework.mq.rabbitmq;
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/config/IailabRedisMQConsumerAutoConfiguration.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/config/IailabRedisMQConsumerAutoConfiguration.java
deleted file mode 100644
index 187f863..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/config/IailabRedisMQConsumerAutoConfiguration.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.iailab.framework.mq.redis.config;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.system.SystemUtil;
-import com.iailab.framework.common.enums.DocumentEnum;
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.mq.redis.core.job.RedisPendingMessageResendJob;
-import com.iailab.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
-import com.iailab.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RedissonClient;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.connection.RedisServerCommands;
-import org.springframework.data.redis.connection.stream.Consumer;
-import org.springframework.data.redis.connection.stream.ObjectRecord;
-import org.springframework.data.redis.connection.stream.ReadOffset;
-import org.springframework.data.redis.connection.stream.StreamOffset;
-import org.springframework.data.redis.core.RedisCallback;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.listener.ChannelTopic;
-import org.springframework.data.redis.listener.RedisMessageListenerContainer;
-import org.springframework.data.redis.stream.StreamMessageListenerContainer;
-import org.springframework.scheduling.annotation.EnableScheduling;
-
-import java.util.List;
-import java.util.Properties;
-
-/**
- * Redis 消息队列 Consumer 配置类
- *
- * @author iailab
- */
-@Slf4j
-@EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息
-@AutoConfiguration(after = IailabRedisAutoConfiguration.class)
-public class IailabRedisMQConsumerAutoConfiguration {
-
-    /**
-     * 创建 Redis Pub/Sub 广播消费的容器
-     */
-    @Bean
-    @ConditionalOnBean(AbstractRedisChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听
-    public RedisMessageListenerContainer redisMessageListenerContainer(
-            RedisMQTemplate redisMQTemplate, List<AbstractRedisChannelMessageListener<?>> listeners) {
-        // 创建 RedisMessageListenerContainer 对象
-        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
-        // 设置 RedisConnection 工厂。
-        container.setConnectionFactory(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory());
-        // 添加监听器
-        listeners.forEach(listener -> {
-            listener.setRedisMQTemplate(redisMQTemplate);
-            container.addMessageListener(listener, new ChannelTopic(listener.getChannel()));
-            log.info("[redisMessageListenerContainer][注册 Channel({}) 对应的监听器({})]",
-                    listener.getChannel(), listener.getClass().getName());
-        });
-        return container;
-    }
-
-    /**
-     * 创建 Redis Stream 重新消费的任务
-     */
-    @Bean
-    @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
-    public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners,
-                                                                     RedisMQTemplate redisTemplate,
-                                                                     @Value("${spring.application.name}") String groupName,
-                                                                     RedissonClient redissonClient) {
-        return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient);
-    }
-
-    /**
-     * 创建 Redis Stream 集群消费的容器
-     *
-     * 基础知识:<a href="https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html">Redis Stream 的 xreadgroup 命令</a>
-     */
-    @Bean(initMethod = "start", destroyMethod = "stop")
-    @ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
-    public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(
-            RedisMQTemplate redisMQTemplate, List<AbstractRedisStreamMessageListener<?>> listeners) {
-        RedisTemplate<String, ?> redisTemplate = redisMQTemplate.getRedisTemplate();
-        checkRedisVersion(redisTemplate);
-        // 第一步,创建 StreamMessageListenerContainer 容器
-        // 创建 options 配置
-        StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
-                StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder()
-                        .batchSize(10) // 一次性最多拉取多少条消息
-                        .targetType(String.class) // 目标类型。统一使用 String,通过自己封装的 AbstractStreamMessageListener 去反序列化
-                        .build();
-        // 创建 container 对象
-        StreamMessageListenerContainer<String, ObjectRecord<String, String>> container =
-                StreamMessageListenerContainer.create(redisMQTemplate.getRedisTemplate().getRequiredConnectionFactory(), containerOptions);
-
-        // 第二步,注册监听器,消费对应的 Stream 主题
-        String consumerName = buildConsumerName();
-        listeners.parallelStream().forEach(listener -> {
-            log.info("[redisStreamMessageListenerContainer][开始注册 StreamKey({}) 对应的监听器({})]",
-                    listener.getStreamKey(), listener.getClass().getName());
-            // 创建 listener 对应的消费者分组
-            try {
-                redisTemplate.opsForStream().createGroup(listener.getStreamKey(), listener.getGroup());
-            } catch (Exception ignore) {
-            }
-            // 设置 listener 对应的 redisTemplate
-            listener.setRedisMQTemplate(redisMQTemplate);
-            // 创建 Consumer 对象
-            Consumer consumer = Consumer.from(listener.getGroup(), consumerName);
-            // 设置 Consumer 消费进度,以最小消费进度为准
-            StreamOffset<String> streamOffset = StreamOffset.create(listener.getStreamKey(), ReadOffset.lastConsumed());
-            // 设置 Consumer 监听
-            StreamMessageListenerContainer.StreamReadRequestBuilder<String> builder = StreamMessageListenerContainer.StreamReadRequest
-                    .builder(streamOffset).consumer(consumer)
-                    .autoAcknowledge(false) // 不自动 ack
-                    .cancelOnError(throwable -> false); // 默认配置,发生异常就取消消费,显然不符合预期;因此,我们设置为 false
-            container.register(builder.build(), listener);
-            log.info("[redisStreamMessageListenerContainer][完成注册 StreamKey({}) 对应的监听器({})]",
-                    listener.getStreamKey(), listener.getClass().getName());
-        });
-        return container;
-    }
-
-    /**
-     * 构建消费者名字,使用本地 IP + 进程编号的方式。
-     * 参考自 RocketMQ clientId 的实现
-     *
-     * @return 消费者名字
-     */
-    private static String buildConsumerName() {
-        return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
-    }
-
-    /**
-     * 校验 Redis 版本号,是否满足最低的版本号要求!
-     */
-    private static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
-        // 获得 Redis 版本
-        Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
-        String version = MapUtil.getStr(info, "redis_version");
-        // 校验最低版本必须大于等于 5.0.0
-        int majorVersion = Integer.parseInt(StrUtil.subBefore(version, '.', false));
-        if (majorVersion < 5) {
-            throw new IllegalStateException(StrUtil.format("您当前的 Redis 版本为 {},小于最低要求的 5.0.0 版本!" +
-                    "请参考 {} 文档进行安装。", version, DocumentEnum.REDIS_INSTALL.getUrl()));
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/config/IailabRedisMQProducerAutoConfiguration.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/config/IailabRedisMQProducerAutoConfiguration.java
deleted file mode 100644
index 249f7f6..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/config/IailabRedisMQProducerAutoConfiguration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.iailab.framework.mq.redis.config;
-
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import java.util.List;
-
-/**
- * Redis 消息队列 Producer 配置类
- *
- * @author iailab
- */
-@Slf4j
-@AutoConfiguration(after = IailabRedisAutoConfiguration.class)
-public class IailabRedisMQProducerAutoConfiguration {
-
-    @Bean
-    public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate,
-                                           List<RedisMessageInterceptor> interceptors) {
-        RedisMQTemplate redisMQTemplate = new RedisMQTemplate(redisTemplate);
-        // 添加拦截器
-        interceptors.forEach(redisMQTemplate::addInterceptor);
-        return redisMQTemplate;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/RedisMQTemplate.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/RedisMQTemplate.java
deleted file mode 100644
index 76009f8..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/RedisMQTemplate.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.iailab.framework.mq.redis.core;
-
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-import com.iailab.framework.mq.redis.core.pubsub.AbstractRedisChannelMessage;
-import com.iailab.framework.mq.redis.core.stream.AbstractRedisStreamMessage;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import org.springframework.data.redis.connection.stream.RecordId;
-import org.springframework.data.redis.connection.stream.StreamRecords;
-import org.springframework.data.redis.core.RedisTemplate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Redis MQ 操作模板类
- *
- * @author iailab
- */
-@AllArgsConstructor
-public class RedisMQTemplate {
-
-    @Getter
-    private final RedisTemplate<String, ?> redisTemplate;
-    /**
-     * 拦截器数组
-     */
-    @Getter
-    private final List<RedisMessageInterceptor> interceptors = new ArrayList<>();
-
-    /**
-     * 发送 Redis 消息,基于 Redis pub/sub 实现
-     *
-     * @param message 消息
-     */
-    public <T extends AbstractRedisChannelMessage> void send(T message) {
-        try {
-            sendMessageBefore(message);
-            // 发送消息
-            redisTemplate.convertAndSend(message.getChannel(), JsonUtils.toJsonString(message));
-        } finally {
-            sendMessageAfter(message);
-        }
-    }
-
-    /**
-     * 发送 Redis 消息,基于 Redis Stream 实现
-     *
-     * @param message 消息
-     * @return 消息记录的编号对象
-     */
-    public <T extends AbstractRedisStreamMessage> RecordId send(T message) {
-        try {
-            sendMessageBefore(message);
-            // 发送消息
-            return redisTemplate.opsForStream().add(StreamRecords.newRecord()
-                    .ofObject(JsonUtils.toJsonString(message)) // 设置内容
-                    .withStreamKey(message.getStreamKey())); // 设置 stream key
-        } finally {
-            sendMessageAfter(message);
-        }
-    }
-
-    /**
-     * 添加拦截器
-     *
-     * @param interceptor 拦截器
-     */
-    public void addInterceptor(RedisMessageInterceptor interceptor) {
-        interceptors.add(interceptor);
-    }
-
-    private void sendMessageBefore(AbstractRedisMessage message) {
-        // 正序
-        interceptors.forEach(interceptor -> interceptor.sendMessageBefore(message));
-    }
-
-    private void sendMessageAfter(AbstractRedisMessage message) {
-        // 倒序
-        for (int i = interceptors.size() - 1; i >= 0; i--) {
-            interceptors.get(i).sendMessageAfter(message);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/interceptor/RedisMessageInterceptor.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/interceptor/RedisMessageInterceptor.java
deleted file mode 100644
index b3f1eae..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/interceptor/RedisMessageInterceptor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.iailab.framework.mq.redis.core.interceptor;
-
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-
-/**
- * {@link AbstractRedisMessage} 消息拦截器
- * 通过拦截器,作为插件机制,实现拓展。
- * 例如说,多租户场景下的 MQ 消息处理
- *
- * @author iailab
- */
-public interface RedisMessageInterceptor {
-
-    default void sendMessageBefore(AbstractRedisMessage message) {
-    }
-
-    default void sendMessageAfter(AbstractRedisMessage message) {
-    }
-
-    default void consumeMessageBefore(AbstractRedisMessage message) {
-    }
-
-    default void consumeMessageAfter(AbstractRedisMessage message) {
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/job/RedisPendingMessageResendJob.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/job/RedisPendingMessageResendJob.java
deleted file mode 100644
index 448c63a..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/job/RedisPendingMessageResendJob.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.iailab.framework.mq.redis.core.job;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.RLock;
-import org.redisson.api.RedissonClient;
-import org.springframework.data.domain.Range;
-import org.springframework.data.redis.connection.stream.*;
-import org.springframework.data.redis.core.StreamOperations;
-import org.springframework.scheduling.annotation.Scheduled;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * 这个任务用于处理,crash 之后的消费者未消费完的消息
- */
-@Slf4j
-@AllArgsConstructor
-public class RedisPendingMessageResendJob {
-
-    private static final String LOCK_KEY = "redis:pending:msg:lock";
-
-    /**
-     * 消息超时时间,默认 5 分钟
-     *
-     * 1. 超时的消息才会被重新投递
-     * 2. 由于定时任务 1 分钟一次,消息超时后不会被立即重投,极端情况下消息5分钟过期后,再等 1 分钟才会被扫瞄到
-     */
-    private static final int EXPIRE_TIME = 5 * 60;
-
-    private final List<AbstractRedisStreamMessageListener<?>> listeners;
-    private final RedisMQTemplate redisTemplate;
-    private final String groupName;
-    private final RedissonClient redissonClient;
-
-    /**
-     * 一分钟执行一次,这里选择每分钟的35秒执行,是为了避免整点任务过多的问题
-     */
-    @Scheduled(cron = "35 * * * * ?")
-    public void messageResend() {
-        RLock lock = redissonClient.getLock(LOCK_KEY);
-        // 尝试加锁
-        if (lock.tryLock()) {
-            try {
-                execute();
-            } catch (Exception ex) {
-                log.error("[messageResend][执行异常]", ex);
-            } finally {
-                lock.unlock();
-            }
-        }
-    }
-
-    /**
-     * 执行清理逻辑
-     *
-     * @see <a href="https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/480/files">讨论</a>
-     */
-    private void execute() {
-        StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream();
-        listeners.forEach(listener -> {
-            PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), groupName));
-            // 每个消费者的 pending 队列消息数量
-            Map<String, Long> pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer();
-            pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> {
-                log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount);
-                // 每个消费者的 pending消息的详情信息
-                PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(groupName, consumerName), Range.unbounded(), pendingMessageCount);
-                if (pendingMessages.isEmpty()) {
-                    return;
-                }
-                pendingMessages.forEach(pendingMessage -> {
-                    // 获取消息上一次传递到 consumer 的时间,
-                    long lastDelivery = pendingMessage.getElapsedTimeSinceLastDelivery().getSeconds();
-                    if (lastDelivery < EXPIRE_TIME){
-                        return;
-                    }
-                    // 获取指定 id 的消息体
-                    List<MapRecord<String, Object, Object>> records = ops.range(listener.getStreamKey(),
-                            Range.of(Range.Bound.inclusive(pendingMessage.getIdAsString()), Range.Bound.inclusive(pendingMessage.getIdAsString())));
-                    if (CollUtil.isEmpty(records)) {
-                        return;
-                    }
-                    // 重新投递消息
-                    redisTemplate.getRedisTemplate().opsForStream().add(StreamRecords.newRecord()
-                            .ofObject(records.get(0).getValue()) // 设置内容
-                            .withStreamKey(listener.getStreamKey()));
-                    // ack 消息消费完成
-                    redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, records.get(0));
-                    log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId());
-                });
-            });
-        });
-    }
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/message/AbstractRedisMessage.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/message/AbstractRedisMessage.java
deleted file mode 100644
index 46b3f88..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/message/AbstractRedisMessage.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.iailab.framework.mq.redis.core.message;
-
-import lombok.Data;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Redis 消息抽象基类
- *
- * @author iailab
- */
-@Data
-public abstract class AbstractRedisMessage {
-
-    /**
-     * 头
-     */
-    private Map<String, String> headers = new HashMap<>();
-
-    public String getHeader(String key) {
-        return headers.get(key);
-    }
-
-    public void addHeader(String key, String value) {
-        headers.put(key, value);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/pubsub/AbstractRedisChannelMessage.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/pubsub/AbstractRedisChannelMessage.java
deleted file mode 100644
index e95d622..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/pubsub/AbstractRedisChannelMessage.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.iailab.framework.mq.redis.core.pubsub;
-
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-/**
- * Redis Channel Message 抽象类
- *
- * @author iailab
- */
-public abstract class AbstractRedisChannelMessage extends AbstractRedisMessage {
-
-    /**
-     * 获得 Redis Channel,默认使用类名
-     *
-     * @return Channel
-     */
-    @JsonIgnore // 避免序列化。原因是,Redis 发布 Channel 消息的时候,已经会指定。
-    public String getChannel() {
-        return getClass().getSimpleName();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java
deleted file mode 100644
index f0f2578..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/pubsub/AbstractRedisChannelMessageListener.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.iailab.framework.mq.redis.core.pubsub;
-
-import cn.hutool.core.util.TypeUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-import lombok.Setter;
-import lombok.SneakyThrows;
-import org.springframework.data.redis.connection.Message;
-import org.springframework.data.redis.connection.MessageListener;
-
-import java.lang.reflect.Type;
-import java.util.List;
-
-/**
- * Redis Pub/Sub 监听器抽象类,用于实现广播消费
- *
- * @param <T> 消息类型。一定要填写噢,不然会报错
- *
- * @author iailab
- */
-public abstract class AbstractRedisChannelMessageListener<T extends AbstractRedisChannelMessage> implements MessageListener {
-
-    /**
-     * 消息类型
-     */
-    private final Class<T> messageType;
-    /**
-     * Redis Channel
-     */
-    private final String channel;
-    /**
-     * RedisMQTemplate
-     */
-    @Setter
-    private RedisMQTemplate redisMQTemplate;
-
-    @SneakyThrows
-    protected AbstractRedisChannelMessageListener() {
-        this.messageType = getMessageClass();
-        this.channel = messageType.getDeclaredConstructor().newInstance().getChannel();
-    }
-
-    /**
-     * 获得 Sub 订阅的 Redis Channel 通道
-     *
-     * @return channel
-     */
-    public final String getChannel() {
-        return channel;
-    }
-
-    @Override
-    public final void onMessage(Message message, byte[] bytes) {
-        T messageObj = JsonUtils.parseObject(message.getBody(), messageType);
-        try {
-            consumeMessageBefore(messageObj);
-            // 消费消息
-            this.onMessage(messageObj);
-        } finally {
-            consumeMessageAfter(messageObj);
-        }
-    }
-
-    /**
-     * 处理消息
-     *
-     * @param message 消息
-     */
-    public abstract void onMessage(T message);
-
-    /**
-     * 通过解析类上的泛型,获得消息类型
-     *
-     * @return 消息类型
-     */
-    @SuppressWarnings("unchecked")
-    private Class<T> getMessageClass() {
-        Type type = TypeUtil.getTypeArgument(getClass(), 0);
-        if (type == null) {
-            throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
-        }
-        return (Class<T>) type;
-    }
-
-    private void consumeMessageBefore(AbstractRedisMessage message) {
-        assert redisMQTemplate != null;
-        List<RedisMessageInterceptor> interceptors = redisMQTemplate.getInterceptors();
-        // 正序
-        interceptors.forEach(interceptor -> interceptor.consumeMessageBefore(message));
-    }
-
-    private void consumeMessageAfter(AbstractRedisMessage message) {
-        assert redisMQTemplate != null;
-        List<RedisMessageInterceptor> interceptors = redisMQTemplate.getInterceptors();
-        // 倒序
-        for (int i = interceptors.size() - 1; i >= 0; i--) {
-            interceptors.get(i).consumeMessageAfter(message);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/stream/AbstractRedisStreamMessage.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/stream/AbstractRedisStreamMessage.java
deleted file mode 100644
index 05743c8..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/stream/AbstractRedisStreamMessage.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.iailab.framework.mq.redis.core.stream;
-
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-/**
- * Redis Stream Message 抽象类
- *
- * @author iailab
- */
-public abstract class AbstractRedisStreamMessage extends AbstractRedisMessage {
-
-    /**
-     * 获得 Redis Stream Key,默认使用类名
-     *
-     * @return Channel
-     */
-    @JsonIgnore // 避免序列化
-    public String getStreamKey() {
-        return getClass().getSimpleName();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/stream/AbstractRedisStreamMessageListener.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/stream/AbstractRedisStreamMessageListener.java
deleted file mode 100644
index 6628611..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/core/stream/AbstractRedisStreamMessageListener.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package com.iailab.framework.mq.redis.core.stream;
-
-import cn.hutool.core.util.TypeUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.mq.redis.core.interceptor.RedisMessageInterceptor;
-import com.iailab.framework.mq.redis.core.message.AbstractRedisMessage;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.SneakyThrows;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.connection.stream.ObjectRecord;
-import org.springframework.data.redis.stream.StreamListener;
-
-import java.lang.reflect.Type;
-import java.util.List;
-
-/**
- * Redis Stream 监听器抽象类,用于实现集群消费
- *
- * @param <T> 消息类型。一定要填写噢,不然会报错
- *
- * @author iailab
- */
-public abstract class AbstractRedisStreamMessageListener<T extends AbstractRedisStreamMessage>
-        implements StreamListener<String, ObjectRecord<String, String>> {
-
-    /**
-     * 消息类型
-     */
-    private final Class<T> messageType;
-    /**
-     * Redis Channel
-     */
-    @Getter
-    private final String streamKey;
-
-    /**
-     * Redis 消费者分组,默认使用 spring.application.name 名字
-     */
-    @Value("${spring.application.name}")
-    @Getter
-    private String group;
-    /**
-     * RedisMQTemplate
-     */
-    @Setter
-    private RedisMQTemplate redisMQTemplate;
-
-    @SneakyThrows
-    protected AbstractRedisStreamMessageListener() {
-        this.messageType = getMessageClass();
-        this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey();
-    }
-
-    @Override
-    public void onMessage(ObjectRecord<String, String> message) {
-        // 消费消息
-        T messageObj = JsonUtils.parseObject(message.getValue(), messageType);
-        try {
-            consumeMessageBefore(messageObj);
-            // 消费消息
-            this.onMessage(messageObj);
-            // ack 消息消费完成
-            redisMQTemplate.getRedisTemplate().opsForStream().acknowledge(group, message);
-            // TODO iailab:需要额外考虑以下几个点:
-            // 1. 处理异常的情况
-            // 2. 发送日志;以及事务的结合
-            // 3. 消费日志;以及通用的幂等性
-            // 4. 消费失败的重试,https://zhuanlan.zhihu.com/p/60501638
-        } finally {
-            consumeMessageAfter(messageObj);
-        }
-    }
-
-    /**
-     * 处理消息
-     *
-     * @param message 消息
-     */
-    public abstract void onMessage(T message);
-
-    /**
-     * 通过解析类上的泛型,获得消息类型
-     *
-     * @return 消息类型
-     */
-    @SuppressWarnings("unchecked")
-    private Class<T> getMessageClass() {
-        Type type = TypeUtil.getTypeArgument(getClass(), 0);
-        if (type == null) {
-            throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
-        }
-        return (Class<T>) type;
-    }
-
-    private void consumeMessageBefore(AbstractRedisMessage message) {
-        assert redisMQTemplate != null;
-        List<RedisMessageInterceptor> interceptors = redisMQTemplate.getInterceptors();
-        // 正序
-        interceptors.forEach(interceptor -> interceptor.consumeMessageBefore(message));
-    }
-
-    private void consumeMessageAfter(AbstractRedisMessage message) {
-        assert redisMQTemplate != null;
-        List<RedisMessageInterceptor> interceptors = redisMQTemplate.getInterceptors();
-        // 倒序
-        for (int i = interceptors.size() - 1; i >= 0; i--) {
-            interceptors.get(i).consumeMessageAfter(message);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/package-info.java b/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/package-info.java
deleted file mode 100644
index 7a386a9..0000000
--- a/iailab-framework/iailab-common-mq/src/main/java/com/iailab/framework/mq/redis/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 消息队列,基于 Redis 提供:
- * 1. 基于 Pub/Sub 实现广播消费
- * 2. 基于 Stream 实现集群消费
- */
-package com.iailab.framework.mq.redis;
diff --git a/iailab-framework/iailab-common-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index c38ac54..0000000
--- a/iailab-framework/iailab-common-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,3 +0,0 @@
-com.iailab.framework.mq.redis.config.IailabRedisMQProducerAutoConfiguration
-com.iailab.framework.mq.redis.config.IailabRedisMQConsumerAutoConfiguration
-com.iailab.framework.mq.rabbitmq.config.IailabRabbitMQAutoConfiguration
diff --git a/iailab-framework/iailab-common-mybatis/pom.xml b/iailab-framework/iailab-common-mybatis/pom.xml
deleted file mode 100644
index 9aa8d58..0000000
--- a/iailab-framework/iailab-common-mybatis/pom.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-mybatis</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>数据库连接池、多数据源、事务、MyBatis 拓展</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-web</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有 OncePerRequestFilter 使用到 -->
-        </dependency>
-
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>com.mysql</groupId>
-            <artifactId>mysql-connector-j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.oracle.database.jdbc</groupId>
-            <artifactId>ojdbc8</artifactId>
-<!--            <optional>true</optional>-->
-        </dependency>
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>com.microsoft.sqlserver</groupId>
-            <artifactId>mssql-jdbc</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>com.dameng</groupId>
-            <artifactId>DmJdbcDriver18</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>druid-spring-boot-starter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>mybatis-plus-boot-starter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.yulichang</groupId>
-            <artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 -->
-        </dependency>
-
-        <dependency>
-            <groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
-            <artifactId>easy-trans-spring-boot-starter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.fhs-opensource</groupId>
-            <artifactId>easy-trans-mybatis-plus-extend</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <version>RELEASE</version>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.alibaba.nacos</groupId>
-            <artifactId>nacos-client</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/dao/BaseDao.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/dao/BaseDao.java
deleted file mode 100644
index 0cdb369..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/dao/BaseDao.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.dao;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-/**
- * 基础Dao
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-public interface BaseDao<T> extends BaseMapper<T> {
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/entity/BaseEntity.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/entity/BaseEntity.java
deleted file mode 100644
index 1a740ce..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/entity/BaseEntity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.entity;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * 基础实体类,所有实体都需要继承
- *
- * @author Mark sunlightcs@gmail.com
- */
-@Data
-public abstract class BaseEntity implements Serializable {
-    /**
-     * id
-     */
-    @TableId
-    private Long id;
-    /**
-     * 创建者
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Long  creator;
-    /**
-     * 创建时间
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Date createDate;
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/package-info.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/package-info.java
deleted file mode 100644
index 44e33fb..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.iailab.framework.common;
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/page/PageData.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/page/PageData.java
deleted file mode 100644
index 64c0822..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/page/PageData.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.page;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * 分页工具类
- *
- * @author Mark sunlightcs@gmail.com
- */
-@Data
-@Tag(name = "分页数据")
-public class PageData<T> implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    @Schema(description = "总记录数")
-    private int total;
-
-    @Schema(description = "列表数据")
-    private List<T> list;
-
-    /**
-     * 分页
-     * @param list   列表数据
-     * @param total  总记录数
-     */
-    public PageData(List<T> list, long total) {
-        this.list = list;
-        this.total = (int)total;
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/BaseService.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/BaseService.java
deleted file mode 100644
index 686441d..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/BaseService.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.service;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-
-import java.io.Serializable;
-import java.util.Collection;
-
-/**
- * 基础服务接口,所有Service接口都要继承
- *
- * @author Mark sunlightcs@gmail.com
- */
-public interface BaseService<T> {
-    Class<T> currentModelClass();
-
-    /**
-     * <p>
-     * 插入一条记录(选择字段,策略插入)
-     * </p>
-     *
-     * @param entity 实体对象
-     */
-    boolean insert(T entity);
-
-    /**
-     * <p>
-     * 插入(批量),该方法不支持 Oracle、SQL Server
-     * </p>
-     *
-     * @param entityList 实体对象集合
-     */
-    boolean insertBatch(Collection<T> entityList);
-
-    /**
-     * <p>
-     * 插入(批量),该方法不支持 Oracle、SQL Server
-     * </p>
-     *
-     * @param entityList 实体对象集合
-     * @param batchSize  插入批次数量
-     */
-    boolean insertBatch(Collection<T> entityList, int batchSize);
-
-    /**
-     * <p>
-     * 根据 ID 选择修改
-     * </p>
-     *
-     * @param entity 实体对象
-     */
-    boolean updateById(T entity);
-
-    /**
-     * <p>
-     * 根据 whereEntity 条件,更新记录
-     * </p>
-     *
-     * @param entity        实体对象
-     * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
-     */
-    boolean update(T entity, Wrapper<T> updateWrapper);
-
-    /**
-     * <p>
-     * 根据ID 批量更新
-     * </p>
-     *
-     * @param entityList 实体对象集合
-     */
-    boolean updateBatchById(Collection<T> entityList);
-
-    /**
-     * <p>
-     * 根据ID 批量更新
-     * </p>
-     *
-     * @param entityList 实体对象集合
-     * @param batchSize  更新批次数量
-     */
-    boolean updateBatchById(Collection<T> entityList, int batchSize);
-
-    /**
-     * <p>
-     * 根据 ID 查询
-     * </p>
-     *
-     * @param id 主键ID
-     */
-    T selectById(Serializable id);
-
-    /**
-     * <p>
-     * 根据 ID 删除
-     * </p>
-     *
-     * @param id 主键ID
-     */
-    boolean deleteById(Serializable id);
-
-    /**
-     * <p>
-     * 删除(根据ID 批量删除)
-     * </p>
-     *
-     * @param idList 主键ID列表
-     */
-    boolean deleteBatchIds(Collection<? extends Serializable> idList);
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/CrudService.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/CrudService.java
deleted file mode 100644
index c8c78cb..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/CrudService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- * <p>
- * https://www.renren.io
- * <p>
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.service;
-
-import com.iailab.framework.common.page.PageData;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- *  CRUD基础服务接口
- *
- * @author Mark sunlightcs@gmail.com
- */
-public interface CrudService<T, D> extends BaseService<T> {
-
-    PageData<D> page(Map<String, Object> params);
-
-    List<D> list(Map<String, Object> params);
-
-    D get(Long id);
-
-    void save(D dto);
-
-    void update(D dto);
-
-    void delete(Long[] ids);
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/impl/BaseServiceImpl.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/impl/BaseServiceImpl.java
deleted file mode 100644
index 51254d7..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/impl/BaseServiceImpl.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.enums.SqlMethod;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.metadata.OrderItem;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
-import com.iailab.framework.common.constant.Constant;
-import com.iailab.framework.common.page.PageData;
-import com.iailab.framework.common.service.BaseService;
-import com.iailab.framework.common.util.object.BeanUtils;
-import org.apache.ibatis.binding.MapperMethod;
-import org.apache.ibatis.logging.Log;
-import org.apache.ibatis.logging.LogFactory;
-import org.apache.ibatis.session.SqlSession;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.function.BiConsumer;
-
-/**
- * 基础服务类,所有Service都要继承
- *
- * @author Mark sunlightcs@gmail.com
- */
-public abstract class BaseServiceImpl<M extends BaseMapper<T>, T>  implements BaseService<T> {
-    @Autowired
-    protected M baseDao;
-    protected Log log = LogFactory.getLog(getClass());
-
-    /**
-     * 获取分页对象
-     * @param params      分页查询参数
-     * @param defaultOrderField  默认排序字段
-     * @param isAsc              排序方式
-     */
-    protected IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
-        //分页参数
-        long curPage = 1;
-        long limit = 10;
-
-        if(params.get(Constant.PAGE) != null){
-            curPage = Long.parseLong((String)params.get(Constant.PAGE));
-        }
-        if(params.get(Constant.LIMIT) != null){
-            limit = Long.parseLong((String)params.get(Constant.LIMIT));
-        }
-
-        //分页对象
-        Page<T> page = new Page<>(curPage, limit);
-
-        //分页参数
-        params.put(Constant.PAGE, page);
-
-        //排序字段
-        String orderField = (String)params.get(Constant.ORDER_FIELD);
-        String order = (String)params.get(Constant.ORDER);
-
-        //前端字段排序
-        if(StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(order)){
-            if(Constant.ASC.equalsIgnoreCase(order)) {
-                return page.addOrder(OrderItem.asc(orderField));
-            }else {
-                return page.addOrder(OrderItem.desc(orderField));
-            }
-        }
-
-        //没有排序字段,则不排序
-        if(StringUtils.isBlank(defaultOrderField)){
-            return page;
-        }
-
-        //默认排序
-        if(isAsc) {
-            page.addOrder(OrderItem.asc(defaultOrderField));
-        }else {
-            page.addOrder(OrderItem.desc(defaultOrderField));
-        }
-
-        return page;
-    }
-
-    protected <T> PageData<T> getPageData(List<?> list, long total, Class<T> target){
-        List<T> targetList = BeanUtils.toBean(list, target);
-
-        return new PageData<>(targetList, total);
-    }
-
-    protected <T> PageData<T> getPageData(IPage page, Class<T> target){
-        return getPageData(page.getRecords(), page.getTotal(), target);
-    }
-
-    protected void paramsToLike(Map<String, Object> params, String... likes){
-        for (String like : likes){
-            String val = (String)params.get(like);
-            if (StringUtils.isNotBlank(val)){
-                params.put(like, "%" + val + "%");
-            }else {
-                params.put(like, null);
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * 判断数据库操作是否成功
-     * </p>
-     * <p>
-     * 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
-     * </p>
-     *
-     * @param result 数据库操作返回影响条数
-     * @return boolean
-     */
-    protected static boolean retBool(Integer result) {
-        return SqlHelper.retBool(result);
-    }
-
-    protected Class<M> currentMapperClass() {
-        return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 0);
-    }
-
-    @Override
-    public Class<T> currentModelClass() {
-        return (Class<T>)ReflectionKit.getSuperClassGenericType(this.getClass(), BaseServiceImpl.class, 1);
-    }
-
-    protected String getSqlStatement(SqlMethod sqlMethod) {
-        return SqlHelper.getSqlStatement(this.currentMapperClass(), sqlMethod);
-    }
-
-    @Override
-    public boolean insert(T entity) {
-        return BaseServiceImpl.retBool(baseDao.insert(entity));
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean insertBatch(Collection<T> entityList) {
-        return insertBatch(entityList, 100);
-    }
-
-    /**
-     * 批量插入
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean insertBatch(Collection<T> entityList, int batchSize) {
-        String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
-        return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
-    }
-
-    /**
-     * 执行批量操作
-     */
-    protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
-        return SqlHelper.executeBatch(this.currentModelClass(), this.log, list, batchSize, consumer);
-    }
-
-
-    @Override
-    public boolean updateById(T entity) {
-        return BaseServiceImpl.retBool(baseDao.updateById(entity));
-    }
-
-    @Override
-    public boolean update(T entity, Wrapper<T> updateWrapper) {
-        return BaseServiceImpl.retBool(baseDao.update(entity, updateWrapper));
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean updateBatchById(Collection<T> entityList) {
-        return updateBatchById(entityList, 30);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean updateBatchById(Collection<T> entityList, int batchSize) {
-        String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
-        return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
-            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
-            param.put(Constants.ENTITY, entity);
-            sqlSession.update(sqlStatement, param);
-        });
-    }
-
-    @Override
-    public T selectById(Serializable id) {
-        return baseDao.selectById(id);
-    }
-
-    @Override
-    public boolean deleteById(Serializable id) {
-        return SqlHelper.retBool(baseDao.deleteById(id));
-    }
-
-    @Override
-    public boolean deleteBatchIds(Collection<? extends Serializable> idList) {
-        return SqlHelper.retBool(baseDao.deleteBatchIds(idList));
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/impl/CrudServiceImpl.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/impl/CrudServiceImpl.java
deleted file mode 100644
index 6b12a43..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/common/service/impl/CrudServiceImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- * <p>
- * https://www.renren.io
- * <p>
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
-import com.iailab.framework.common.page.PageData;
-import com.iailab.framework.common.service.CrudService;
-import com.iailab.framework.common.util.object.ConvertUtils;
-import org.springframework.beans.BeanUtils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- *  CRUD基础服务类
- *
- * @author Mark sunlightcs@gmail.com
- */
-public abstract class CrudServiceImpl<M extends BaseMapper<T>, T, D> extends BaseServiceImpl<M, T> implements CrudService<T, D> {
-
-    protected Class<D> currentDtoClass() {
-        return (Class<D>)ReflectionKit.getSuperClassGenericType(getClass(), CrudServiceImpl.class, 2);
-    }
-
-    @Override
-    public PageData<D> page(Map<String, Object> params) {
-        IPage<T> page = baseDao.selectPage(
-            getPage(params, null, false),
-            getWrapper(params)
-        );
-
-        return getPageData(page, currentDtoClass());
-    }
-
-    @Override
-    public List<D> list(Map<String, Object> params) {
-        List<T> entityList = baseDao.selectList(getWrapper(params));
-
-        return ConvertUtils.sourceToTarget(entityList, currentDtoClass());
-    }
-
-    public abstract QueryWrapper<T> getWrapper(Map<String, Object> params);
-
-    @Override
-    public D get(Long id) {
-        T entity = baseDao.selectById(id);
-
-        return ConvertUtils.sourceToTarget(entity, currentDtoClass());
-    }
-
-    @Override
-    public void save(D dto) {
-        T entity = ConvertUtils.sourceToTarget(dto, currentModelClass());
-        insert(entity);
-
-        //copy主键值到dto
-        BeanUtils.copyProperties(entity, dto);
-    }
-
-    @Override
-    public void update(D dto) {
-        T entity = ConvertUtils.sourceToTarget(dto, currentModelClass());
-        updateById(entity);
-    }
-
-    @Override
-    public void delete(Long[] ids) {
-        baseDao.deleteBatchIds(Arrays.asList(ids));
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/config/IailabDataSourceAutoConfiguration.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/config/IailabDataSourceAutoConfiguration.java
deleted file mode 100644
index 27d252d..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/config/IailabDataSourceAutoConfiguration.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.datasource.config;
-
-import com.iailab.framework.datasource.core.filter.DruidAdRemoveFilter;
-import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-/**
- * 数据库配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理
-@EnableConfigurationProperties(DruidStatProperties.class)
-public class IailabDataSourceAutoConfiguration {
-
-    /**
-     * 创建 DruidAdRemoveFilter 过滤器,过滤 common.js 的广告
-     */
-    @Bean
-    @ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
-    public FilterRegistrationBean<DruidAdRemoveFilter> druidAdRemoveFilterFilter(DruidStatProperties properties) {
-        // 获取 druid web 监控页面的参数
-        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
-        // 提取 common.js 的配置路径
-        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
-        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
-        // 创建 DruidAdRemoveFilter Bean
-        FilterRegistrationBean<DruidAdRemoveFilter> registrationBean = new FilterRegistrationBean<>();
-        registrationBean.setFilter(new DruidAdRemoveFilter());
-        registrationBean.addUrlPatterns(commonJsPattern);
-        return registrationBean;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/core/enums/DataSourceEnum.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/core/enums/DataSourceEnum.java
deleted file mode 100644
index 0617e5e..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/core/enums/DataSourceEnum.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.datasource.core.enums;
-
-/**
- * 对应于多数据源中不同数据源配置
- *
- * 通过在方法上,使用 {@link com.baomidou.dynamic.datasource.annotation.DS} 注解,设置使用的数据源。
- * 注意,默认是 {@link #MASTER} 数据源
- *
- * 对应官方文档为 http://dynamic-datasource.com/guide/customize/Annotation.html
- */
-public interface DataSourceEnum {
-
-    /**
-     * 主库,推荐使用 {@link com.baomidou.dynamic.datasource.annotation.Master} 注解
-     */
-    String MASTER = "master";
-    /**
-     * 从库,推荐使用 {@link com.baomidou.dynamic.datasource.annotation.Slave} 注解
-     */
-    String SLAVE = "slave";
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/core/filter/DruidAdRemoveFilter.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/core/filter/DruidAdRemoveFilter.java
deleted file mode 100644
index cd54d0c..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/core/filter/DruidAdRemoveFilter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.iailab.framework.datasource.core.filter;
-
-import com.alibaba.druid.util.Utils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * Druid 底部广告过滤器
- *
- * @author iailab
- */
-public class DruidAdRemoveFilter extends OncePerRequestFilter {
-
-    /**
-     * common.js 的路径
-     */
-    private static final String COMMON_JS_ILE_PATH = "support/http/resources/js/common.js";
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        chain.doFilter(request, response);
-        // 重置缓冲区,响应头不会被重置
-        response.resetBuffer();
-        // 获取 common.js
-        String text = Utils.readFromResource(COMMON_JS_ILE_PATH);
-        // 正则替换 banner, 除去底部的广告信息
-        text = text.replaceAll("<a.*?banner\"></a><br/>", "");
-        text = text.replaceAll("powered.*?shrek.wang</a>", "");
-        response.getWriter().write(text);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/package-info.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/package-info.java
deleted file mode 100644
index fa02238..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/datasource/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * 数据库连接池,采用 Druid
- * 多数据源,采用爆米花
- */
-package com.iailab.framework.datasource;
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IailabMybatisAutoConfiguration.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IailabMybatisAutoConfiguration.java
deleted file mode 100644
index 5ee2990..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IailabMybatisAutoConfiguration.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.iailab.framework.mybatis.config;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.mybatis.core.enums.SqlConstants;
-import com.iailab.framework.mybatis.core.handler.DefaultDBFieldHandler;
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
-import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
-import com.baomidou.mybatisplus.extension.incrementer.*;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import org.apache.ibatis.annotations.Mapper;
-import org.mybatis.spring.annotation.MapperScan;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-/**
- * MyBaits 配置类
- *
- * @author iailab
- */
-@AutoConfiguration(before = MybatisPlusAutoConfiguration.class) // 目的:先于 MyBatis Plus 自动配置,避免 @MapperScan 可能扫描不到 Mapper 打印 warn 日志
-@MapperScan(value = "${iailab.info.base-package}", annotationClass = Mapper.class,
-        lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
-public class IailabMybatisAutoConfiguration {
-
-    @Bean
-    public MybatisPlusInterceptor mybatisPlusInterceptor() {
-        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
-        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
-        return mybatisPlusInterceptor;
-    }
-
-    @Bean
-    public MetaObjectHandler defaultMetaObjectHandler(){
-        return new DefaultDBFieldHandler(); // 自动填充参数类
-    }
-
-    @Bean
-    @ConditionalOnProperty(prefix = "mybatis-plus.global-config.db-config", name = "id-type", havingValue = "INPUT")
-    public IKeyGenerator keyGenerator(ConfigurableEnvironment environment) {
-        DbType dbType = IdTypeEnvironmentPostProcessor.getDbType(environment);
-        if (dbType != null) {
-            switch (dbType) {
-                case POSTGRE_SQL:
-                    return new PostgreKeyGenerator();
-                case ORACLE:
-                case ORACLE_12C:
-                    return new OracleKeyGenerator();
-                case H2:
-                    return new H2KeyGenerator();
-                case KINGBASE_ES:
-                    return new KingbaseKeyGenerator();
-                case DM:
-                    return new DmKeyGenerator();
-            }
-        }
-        // 找不到合适的 IKeyGenerator 实现类
-        throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IdTypeEnvironmentPostProcessor.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IdTypeEnvironmentPostProcessor.java
deleted file mode 100644
index 16ae754..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/IdTypeEnvironmentPostProcessor.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.iailab.framework.mybatis.config;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.collection.SetUtils;
-import com.iailab.framework.mybatis.core.enums.SqlConstants;
-import com.iailab.framework.mybatis.core.util.JdbcUtils;
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.annotation.IdType;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.env.EnvironmentPostProcessor;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-import java.util.Set;
-
-/**
- * 当 IdType 为 {@link IdType#NONE} 时,根据 PRIMARY 数据源所使用的数据库,自动设置
- *
- * @author iailab
- */
-@Slf4j
-public class IdTypeEnvironmentPostProcessor implements EnvironmentPostProcessor {
-
-    private static final String ID_TYPE_KEY = "mybatis-plus.global-config.db-config.id-type";
-
-    private static final String DATASOURCE_DYNAMIC_KEY = "spring.datasource.dynamic";
-
-    private static final String QUARTZ_JOB_STORE_DRIVER_KEY = "spring.quartz.properties.org.quartz.jobStore.driverDelegateClass";
-
-    private static final Set<DbType> INPUT_ID_TYPES = SetUtils.asSet(DbType.ORACLE, DbType.ORACLE_12C,
-            DbType.POSTGRE_SQL, DbType.KINGBASE_ES, DbType.DB2, DbType.H2);
-
-    @Override
-    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
-        // 如果获取不到 DbType,则不进行处理
-        DbType dbType = getDbType(environment);
-        if (dbType == null) {
-            return;
-        }
-
-        // 设置 Quartz JobStore 对应的 Driver
-        // TODO iailab:暂时没有找到特别合适的地方,先放在这里
-        setJobStoreDriverIfPresent(environment, dbType);
-        // 初始化 SQL 静态变量
-        SqlConstants.init(dbType);
-        // 如果非 NONE,则不进行处理
-        IdType idType = getIdType(environment);
-        if (idType != IdType.NONE) {
-            return;
-        }
-        // 情况一,用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库
-        if (INPUT_ID_TYPES.contains(dbType)) {
-            setIdType(environment, IdType.INPUT);
-            return;
-        }
-        // 情况二,自增 ID,适合 MySQL 等直接自增的数据库
-        setIdType(environment, IdType.AUTO);
-    }
-
-    public IdType getIdType(ConfigurableEnvironment environment) {
-        return environment.getProperty(ID_TYPE_KEY, IdType.class);
-    }
-
-    public void setIdType(ConfigurableEnvironment environment, IdType idType) {
-        environment.getSystemProperties().put(ID_TYPE_KEY, idType);
-        log.info("[setIdType][修改 MyBatis Plus 的 idType 为({})]", idType);
-    }
-
-    public void setJobStoreDriverIfPresent(ConfigurableEnvironment environment, DbType dbType) {
-        String driverClass = environment.getProperty(QUARTZ_JOB_STORE_DRIVER_KEY);
-        if (StrUtil.isNotEmpty(driverClass)) {
-            return;
-        }
-        // 根据 dbType 类型,获取对应的 driverClass
-        switch (dbType) {
-            case POSTGRE_SQL:
-                driverClass = "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate";
-                break;
-            case ORACLE:
-            case ORACLE_12C:
-                driverClass = "org.quartz.impl.jdbcjobstore.oracle.OracleDelegate";
-                break;
-            case SQL_SERVER:
-            case SQL_SERVER2005:
-                driverClass = "org.quartz.impl.jdbcjobstore.MSSQLDelegate";
-                break;
-        }
-        // 设置 driverClass 变量
-        if (StrUtil.isNotEmpty(driverClass)) {
-            environment.getSystemProperties().put(QUARTZ_JOB_STORE_DRIVER_KEY, driverClass);
-        }
-    }
-
-    public static DbType getDbType(ConfigurableEnvironment environment) {
-        String primary = environment.getProperty(DATASOURCE_DYNAMIC_KEY + "." + "primary");
-        if (StrUtil.isEmpty(primary)) {
-            return null;
-        }
-        String url = environment.getProperty(DATASOURCE_DYNAMIC_KEY + ".datasource." + primary + ".url");
-        if (StrUtil.isEmpty(url)) {
-            return null;
-        }
-        return JdbcUtils.getDbType(url);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/MyBatisConfiguration.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/MyBatisConfiguration.java
deleted file mode 100644
index e841574..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/config/MyBatisConfiguration.java
+++ /dev/null
@@ -1,84 +0,0 @@
-//package com.iailab.framework.mybatis.config;
-//
-//import com.alibaba.fastjson.JSONArray;
-//import com.alibaba.fastjson.JSONObject;
-//import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-//import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
-//import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
-//import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-//import com.iailab.framework.mybatis.core.handler.MybatisHandler;
-//import com.iailab.framework.mybatis.interceptor.DataFilterInterceptor;
-//import org.apache.ibatis.session.SqlSessionFactory;
-//import org.apache.ibatis.type.JdbcType;
-//import org.mybatis.spring.SqlSessionFactoryBean;
-//import org.mybatis.spring.SqlSessionTemplate;
-//import org.springframework.beans.factory.annotation.Value;
-//import org.springframework.boot.jdbc.DataSourceBuilder;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.context.annotation.Primary;
-//import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-//import org.springframework.jdbc.datasource.DataSourceTransactionManager;
-//
-//
-///**
-// * @author houzhongjian
-// * @Title: MyBatisConfiguration
-// * @ProjectName design-parent
-// * @Description: 解决独立启动某个服务时报错问题 No typehandler found for property sqlSessionTemplate
-// * @date 2024/7/2 16:35
-// */
-//@Configuration
-//public class MyBatisConfiguration {
-//
-//    //  配置mapper的扫描,找到所有的mapper.xml映射文件
-////    @Value("${iailab.info.base-package}")
-//    @Value("${mybatis-plus.mapper-locations}")
-//    private String mapperLocations;
-//
-//    @Bean
-//    @Primary
-//    public SqlSessionFactory sqlSessionFactory() throws Exception {
-//        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
-//        sqlSessionFactoryBean.setDataSource(DataSourceBuilder.create().build());
-//        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
-//        sqlSessionFactoryBean.setConfiguration(buildConfiguration());
-//        return sqlSessionFactoryBean.getObject();
-//    }
-//
-//    @Bean
-//    @Primary
-//    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
-//        return  new SqlSessionTemplate(sqlSessionFactory());
-//    }
-//
-//    @Bean
-//    @Primary
-//    public DataSourceTransactionManager transactionManager() {
-//        return new DataSourceTransactionManager(DataSourceBuilder.create().build());
-//    }
-//
-//    private org.apache.ibatis.session.Configuration buildConfiguration() {
-//        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
-//        configuration.getTypeHandlerRegistry().register(JSONObject.class, JdbcType.VARCHAR, MybatisHandler.class);
-//        configuration.getTypeHandlerRegistry().register(JSONArray.class, JdbcType.VARCHAR, MybatisHandler.class);
-//        return configuration;
-//    }
-//
-//    @Bean
-//    public MybatisPlusInterceptor mybatisPlusInterceptor() {
-//        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
-//        // 数据权限
-//        mybatisPlusInterceptor.addInnerInterceptor(new DataFilterInterceptor());
-//        // 分页插件
-//        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
-//        // 乐观锁
-//        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
-//        // 防止全表更新与删除
-//        mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
-//
-//        return mybatisPlusInterceptor;
-//    }
-//
-//
-//}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/dataobject/BaseDO.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/dataobject/BaseDO.java
deleted file mode 100644
index 8c97c70..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/dataobject/BaseDO.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.iailab.framework.mybatis.core.dataobject;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fhs.core.trans.vo.TransPojo;
-import lombok.Data;
-import org.apache.ibatis.type.JdbcType;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 基础实体对象
- *
- * 为什么实现 {@link TransPojo} 接口?
- * 因为使用 Easy-Trans TransType.SIMPLE 模式,集成 MyBatis Plus 查询
- *
- * @author iailab
- */
-@Data
-@JsonIgnoreProperties(value = "transMap") // 由于 Easy-Trans 会添加 transMap 属性,避免 Jackson 在 Spring Cache 反序列化报错
-public abstract class BaseDO implements Serializable, TransPojo {
-
-    /**
-     * 创建时间
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private LocalDateTime createTime;
-    /**
-     * 最后更新时间
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private LocalDateTime updateTime;
-    /**
-     * 创建者,目前使用 SysUser 的 id 编号
-     *
-     * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
-     */
-    @TableField(fill = FieldFill.INSERT, jdbcType = JdbcType.VARCHAR)
-    private String creator;
-    /**
-     * 更新者,目前使用 SysUser 的 id 编号
-     *
-     * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.VARCHAR)
-    private String updater;
-    /**
-     * 是否删除
-     */
-    @TableLogic
-    private Boolean deleted;
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/enums/DbTypeEnum.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/enums/DbTypeEnum.java
deleted file mode 100644
index 644d1e3..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/enums/DbTypeEnum.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.iailab.framework.mybatis.core.enums;
-
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.annotation.DbType;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * 针对 MyBatis Plus 的 {@link DbType} 增强,补充更多信息
- */
-@Getter
-@AllArgsConstructor
-public enum DbTypeEnum {
-
-    /**
-     * MySQL
-     */
-    MY_SQL( DbType.MYSQL, "MySQL", "FIND_IN_SET('#{value}', #{column}) <> 0"),
-
-    /**
-     * Oracle
-     */
-    ORACLE(DbType.ORACLE, "Oracle", "FIND_IN_SET('#{value}', #{column}) <> 0"),
-
-    /**
-     * PostgreSQL
-     *
-     * 华为 openGauss 使用 ProductName 与 PostgreSQL 相同
-     */
-    POSTGRE_SQL(DbType.POSTGRE_SQL,"PostgreSQL", "POSITION('#{value}' IN #{column}) <> 0"),
-
-    /**
-     * SQL Server
-     */
-    SQL_SERVER(DbType.SQL_SERVER, "Microsoft SQL Server", "CHARINDEX(',' + #{value} + ',', ',' + #{column} + ',') <> 0"),
-
-    /**
-     * 达梦
-     */
-    DM(DbType.DM, "DM DBMS", "FIND_IN_SET('#{value}', #{column}) <> 0"),
-
-    /**
-     * 人大金仓
-     */
-    KINGBASE_ES(DbType.KINGBASE_ES, "KingbaseES", "POSITION('#{value}' IN #{column}) <> 0"),
-    ;
-
-    public static final Map<String, DbTypeEnum> MAP_BY_NAME = Arrays.stream(values())
-            .collect(Collectors.toMap(DbTypeEnum::getProductName, Function.identity()));
-
-    public static final Map<DbType, DbTypeEnum> MAP_BY_MP = Arrays.stream(values())
-            .collect(Collectors.toMap(DbTypeEnum::getMpDbType, Function.identity()));
-
-    /**
-     * MyBatis Plus 类型
-     */
-    private final DbType mpDbType;
-    /**
-     * 数据库产品名
-     */
-    private final String productName;
-    /**
-     * SQL FIND_IN_SET 模板
-     */
-    private final String findInSetTemplate;
-
-    public static DbType find(String databaseProductName) {
-        if (StrUtil.isBlank(databaseProductName)) {
-            return null;
-        }
-        return MAP_BY_NAME.get(databaseProductName).getMpDbType();
-    }
-
-    public static String getFindInSetTemplate(DbType dbType) {
-        return Optional.of(MAP_BY_MP.get(dbType).getFindInSetTemplate())
-                .orElseThrow(() -> new IllegalArgumentException("FIND_IN_SET not supported"));
-    }
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/enums/SqlConstants.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/enums/SqlConstants.java
deleted file mode 100644
index 5ba0046..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/enums/SqlConstants.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.mybatis.core.enums;
-
-import com.baomidou.mybatisplus.annotation.DbType;
-
-/**
- * SQL相关常量类
- *
- * @author iailab
- */
-public class SqlConstants {
-
-    /**
-     * 数据库的类型
-     */
-    // TODO 此处使用nacos配置文件的话,先初始化nacos配置才初始化dbType,导致读不到值。暂时先固定Mysql
-    public static DbType DB_TYPE = DbType.MYSQL;
-
-    public static void init(DbType dbType) {
-        DB_TYPE = dbType;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/handler/DefaultDBFieldHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/handler/DefaultDBFieldHandler.java
deleted file mode 100644
index f047f87..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/handler/DefaultDBFieldHandler.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.iailab.framework.mybatis.core.handler;
-
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import org.apache.ibatis.reflection.MetaObject;
-
-import java.time.LocalDateTime;
-import java.util.Objects;
-
-/**
- * 通用参数填充实现类
- *
- * 如果没有显式的对通用参数进行赋值,这里会对通用参数进行填充、赋值
- *
- * @author hexiaowu
- */
-public class DefaultDBFieldHandler implements MetaObjectHandler {
-
-    @Override
-    public void insertFill(MetaObject metaObject) {
-        if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
-            BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
-
-            LocalDateTime current = LocalDateTime.now();
-            // 创建时间为空,则以当前时间为插入时间
-            if (Objects.isNull(baseDO.getCreateTime())) {
-                baseDO.setCreateTime(current);
-            }
-            // 更新时间为空,则以当前时间为更新时间
-            if (Objects.isNull(baseDO.getUpdateTime())) {
-                baseDO.setUpdateTime(current);
-            }
-
-            Long userId = WebFrameworkUtils.getLoginUserId();
-            // 当前登录用户不为空,创建人为空,则当前登录用户为创建人
-            if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
-                baseDO.setCreator(userId.toString());
-            }
-            // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
-            if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
-                baseDO.setUpdater(userId.toString());
-            }
-        }
-    }
-
-    @Override
-    public void updateFill(MetaObject metaObject) {
-        // 更新时间为空,则以当前时间为更新时间
-        Object modifyTime = getFieldValByName("updateTime", metaObject);
-        if (Objects.isNull(modifyTime)) {
-            setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
-        }
-
-        // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
-        Object modifier = getFieldValByName("updater", metaObject);
-        Long userId = WebFrameworkUtils.getLoginUserId();
-        if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
-            setFieldValByName("updater", userId.toString(), metaObject);
-        }
-    }
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/handler/MybatisHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/handler/MybatisHandler.java
deleted file mode 100644
index c7653fe..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/handler/MybatisHandler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.iailab.framework.mybatis.core.handler;
-
-import com.alibaba.fastjson.JSON;
-import org.apache.ibatis.type.BaseTypeHandler;
-import org.apache.ibatis.type.JdbcType;
-
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-public class MybatisHandler extends BaseTypeHandler<Object> {
-
-    @Override
-    public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
-        preparedStatement.setString(i, JSON.toJSONString(o));
-    }
-
-    @Override
-    public Object getNullableResult(ResultSet resultSet, String s) throws SQLException {
-        String sqlJson = resultSet.getString(s);
-        if (null != sqlJson) {
-            return JSON.parse(sqlJson);
-        }
-        return null;
-    }
-
-    @Override
-    public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
-        String sqlJson = resultSet.getString(i);
-        if (null != sqlJson) {
-            return JSON.parse(sqlJson);
-        }
-        return null;
-    }
-
-    @Override
-    public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
-        String sqlJson = callableStatement.getString(i);
-        if (null != sqlJson) {
-            return JSON.parse(sqlJson);
-        }
-        return null;
-    }
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/mapper/BaseMapperX.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/mapper/BaseMapperX.java
deleted file mode 100644
index ccf2c77..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/mapper/BaseMapperX.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package com.iailab.framework.mybatis.core.mapper;
-
-import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.iailab.framework.common.pojo.PageParam;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.pojo.SortablePageParam;
-import com.iailab.framework.common.pojo.SortingField;
-import com.iailab.framework.mybatis.core.enums.SqlConstants;
-import com.iailab.framework.mybatis.core.util.MyBatisUtils;
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import com.baomidou.mybatisplus.extension.toolkit.Db;
-import com.github.yulichang.base.MPJBaseMapper;
-import com.github.yulichang.interfaces.MPJBaseJoin;
-import com.github.yulichang.wrapper.MPJLambdaWrapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
- *
- * 1. {@link BaseMapper} 为 MyBatis Plus 的基础接口,提供基础的 CRUD 能力
- * 2. {@link MPJBaseMapper} 为 MyBatis Plus Join 的基础接口,提供连表 Join 能力
- */
-public interface BaseMapperX<T> extends MPJBaseMapper<T> {
-
-    /**
-     * 获取分页对象
-     * @param params      分页查询参数
-     */
-    default IPage<T> getPage(PageParam params) {
-        //分页参数
-        long curPage = 1;
-        long limit = 10;
-
-        if(params.getPageNo() != null){
-            curPage = params.getPageNo();
-        }
-        if(params.getPageSize() != null){
-            limit = params.getPageSize();
-        }
-
-        //分页对象
-        return new Page<>(curPage, limit);
-    }
-
-    default PageResult<T> selectPage(SortablePageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
-        return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper);
-    }
-
-    default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
-        return selectPage(pageParam, null, queryWrapper);
-    }
-
-    default PageResult<T> selectPage(PageParam pageParam, Collection<SortingField> sortingFields, @Param("ew") Wrapper<T> queryWrapper) {
-        // 特殊:不分页,直接查询全部
-        if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
-            List<T> list = selectList(queryWrapper);
-            return new PageResult<>(list, (long) list.size());
-        }
-
-        // MyBatis Plus 查询
-        IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
-        selectPage(mpPage, queryWrapper);
-        // 转换返回
-        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
-    }
-
-    default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
-        // 特殊:不分页,直接查询全部
-        if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
-            List<D> list = selectJoinList(clazz, lambdaWrapper);
-            return new PageResult<>(list, (long) list.size());
-        }
-
-        // MyBatis Plus Join 查询
-        IPage<D> mpPage = MyBatisUtils.buildPage(pageParam);
-        mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper);
-        // 转换返回
-        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
-    }
-
-    default <DTO> PageResult<DTO> selectJoinPage(PageParam pageParam, Class<DTO> resultTypeClass, MPJBaseJoin<T> joinQueryWrapper) {
-        IPage<DTO> mpPage = MyBatisUtils.buildPage(pageParam);
-        selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper);
-        // 转换返回
-        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
-    }
-
-    default T selectOne(String field, Object value) {
-        return selectOne(new QueryWrapper<T>().eq(field, value));
-    }
-
-    default T selectOne(SFunction<T, ?> field, Object value) {
-        return selectOne(new LambdaQueryWrapper<T>().eq(field, value));
-    }
-
-    default T selectOne(String field1, Object value1, String field2, Object value2) {
-        return selectOne(new QueryWrapper<T>().eq(field1, value1).eq(field2, value2));
-    }
-
-    default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
-        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
-    }
-
-    default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
-                        SFunction<T, ?> field3, Object value3) {
-        return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
-                .eq(field3, value3));
-    }
-
-    default Long selectCount() {
-        return selectCount(new QueryWrapper<>());
-    }
-
-    default Long selectCount(String field, Object value) {
-        return selectCount(new QueryWrapper<T>().eq(field, value));
-    }
-
-    default Long selectCount(SFunction<T, ?> field, Object value) {
-        return selectCount(new LambdaQueryWrapper<T>().eq(field, value));
-    }
-
-    default List<T> selectList() {
-        return selectList(new QueryWrapper<>());
-    }
-
-    default List<T> selectList(String field, Object value) {
-        return selectList(new QueryWrapper<T>().eq(field, value));
-    }
-
-    default List<T> selectList(SFunction<T, ?> field, Object value) {
-        return selectList(new LambdaQueryWrapper<T>().eq(field, value));
-    }
-
-    default List<T> selectList(String field, Collection<?> values) {
-        if (CollUtil.isEmpty(values)) {
-            return CollUtil.newArrayList();
-        }
-        return selectList(new QueryWrapper<T>().in(field, values));
-    }
-
-    default List<T> selectList(SFunction<T, ?> field, Collection<?> values) {
-        if (CollUtil.isEmpty(values)) {
-            return CollUtil.newArrayList();
-        }
-        return selectList(new LambdaQueryWrapper<T>().in(field, values));
-    }
-
-    @Deprecated
-    default List<T> selectList(SFunction<T, ?> leField, SFunction<T, ?> geField, Object value) {
-        return selectList(new LambdaQueryWrapper<T>().le(leField, value).ge(geField, value));
-    }
-
-    default List<T> selectList(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
-        return selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
-    }
-
-    /**
-     * 批量插入,适合大量数据插入
-     *
-     * @param entities 实体们
-     */
-    default Boolean insertBatch(Collection<T> entities) {
-        // 特殊:SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
-        if (Objects.equals(SqlConstants.DB_TYPE, DbType.SQL_SERVER)) {
-            entities.forEach(this::insert);
-            return CollUtil.isNotEmpty(entities);
-        }
-        return Db.saveBatch(entities);
-    }
-
-    /**
-     * 批量插入,适合大量数据插入
-     *
-     * @param entities 实体们
-     * @param size     插入数量 Db.saveBatch 默认为 1000
-     */
-    default Boolean insertBatch(Collection<T> entities, int size) {
-        // 特殊:SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
-        if (Objects.equals(SqlConstants.DB_TYPE, DbType.SQL_SERVER)) {
-            entities.forEach(this::insert);
-            return CollUtil.isNotEmpty(entities);
-        }
-        return Db.saveBatch(entities, size);
-    }
-
-    default int updateBatch(T update) {
-        return update(update, new QueryWrapper<>());
-    }
-
-    default Boolean updateBatch(Collection<T> entities) {
-        return Db.updateBatchById(entities);
-    }
-
-    default Boolean updateBatch(Collection<T> entities, int size) {
-        return Db.updateBatchById(entities, size);
-    }
-
-    default boolean insertOrUpdate(T entity) {
-        return  Db.saveOrUpdate(entity);
-    }
-
-    default Boolean insertOrUpdateBatch(Collection<T> collection) {
-        return Db.saveOrUpdateBatch(collection);
-    }
-
-    default int delete(String field, String value) {
-        return delete(new QueryWrapper<T>().eq(field, value));
-    }
-
-    default int delete(SFunction<T, ?> field, Object value) {
-        return delete(new LambdaQueryWrapper<T>().eq(field, value));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/LambdaQueryWrapperX.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/LambdaQueryWrapperX.java
deleted file mode 100644
index cfca5c9..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/LambdaQueryWrapperX.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.iailab.framework.mybatis.core.query;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import org.springframework.util.StringUtils;
-
-import java.util.Collection;
-
-/**
- * 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
- * <p>
- * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
- *
- * @param <T> 数据类型
- */
-public class LambdaQueryWrapperX<T> extends LambdaQueryWrapper<T> {
-
-    public LambdaQueryWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {
-        if (StringUtils.hasText(val)) {
-            return (LambdaQueryWrapperX<T>) super.like(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {
-        if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
-            return (LambdaQueryWrapperX<T>) super.in(column, values);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {
-        if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
-            return (LambdaQueryWrapperX<T>) super.in(column, values);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {
-        if (ObjectUtil.isNotEmpty(val)) {
-            return (LambdaQueryWrapperX<T>) super.eq(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {
-        if (ObjectUtil.isNotEmpty(val)) {
-            return (LambdaQueryWrapperX<T>) super.ne(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (LambdaQueryWrapperX<T>) super.gt(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (LambdaQueryWrapperX<T>) super.ge(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (LambdaQueryWrapperX<T>) super.lt(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (LambdaQueryWrapperX<T>) super.le(column, val);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {
-        if (val1 != null && val2 != null) {
-            return (LambdaQueryWrapperX<T>) super.between(column, val1, val2);
-        }
-        if (val1 != null) {
-            return (LambdaQueryWrapperX<T>) ge(column, val1);
-        }
-        if (val2 != null) {
-            return (LambdaQueryWrapperX<T>) le(column, val2);
-        }
-        return this;
-    }
-
-    public LambdaQueryWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {
-        Object val1 = ArrayUtils.get(values, 0);
-        Object val2 = ArrayUtils.get(values, 1);
-        return betweenIfPresent(column, val1, val2);
-    }
-
-    // ========== 重写父类方法,方便链式调用 ==========
-
-    @Override
-    public LambdaQueryWrapperX<T> eq(boolean condition, SFunction<T, ?> column, Object val) {
-        super.eq(condition, column, val);
-        return this;
-    }
-
-    @Override
-    public LambdaQueryWrapperX<T> eq(SFunction<T, ?> column, Object val) {
-        super.eq(column, val);
-        return this;
-    }
-
-    @Override
-    public LambdaQueryWrapperX<T> orderByDesc(SFunction<T, ?> column) {
-        super.orderByDesc(true, column);
-        return this;
-    }
-
-    @Override
-    public LambdaQueryWrapperX<T> last(String lastSql) {
-        super.last(lastSql);
-        return this;
-    }
-
-    @Override
-    public LambdaQueryWrapperX<T> in(SFunction<T, ?> column, Collection<?> coll) {
-        super.in(column, coll);
-        return this;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/MPJLambdaWrapperX.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/MPJLambdaWrapperX.java
deleted file mode 100644
index fa8ebc7..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/MPJLambdaWrapperX.java
+++ /dev/null
@@ -1,313 +0,0 @@
-package com.iailab.framework.mybatis.core.query;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import com.github.yulichang.toolkit.MPJWrappers;
-import com.github.yulichang.wrapper.MPJLambdaWrapper;
-import org.springframework.util.StringUtils;
-
-import java.util.Collection;
-import java.util.function.Consumer;
-
-/**
- * 拓展 MyBatis Plus Join QueryWrapper 类,主要增加如下功能:
- * <p>
- * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
- *
- * @param <T> 数据类型
- */
-public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
-
-    public MPJLambdaWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {
-        MPJWrappers.lambdaJoin().like(column, val);
-        if (StringUtils.hasText(val)) {
-            return (MPJLambdaWrapperX<T>) super.like(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {
-        if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
-            return (MPJLambdaWrapperX<T>) super.in(column, values);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {
-        if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
-            return (MPJLambdaWrapperX<T>) super.in(column, values);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {
-        if (ObjectUtil.isNotEmpty(val)) {
-            return (MPJLambdaWrapperX<T>) super.eq(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {
-        if (ObjectUtil.isNotEmpty(val)) {
-            return (MPJLambdaWrapperX<T>) super.ne(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (MPJLambdaWrapperX<T>) super.gt(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (MPJLambdaWrapperX<T>) super.ge(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (MPJLambdaWrapperX<T>) super.lt(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {
-        if (val != null) {
-            return (MPJLambdaWrapperX<T>) super.le(column, val);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {
-        if (val1 != null && val2 != null) {
-            return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
-        }
-        if (val1 != null) {
-            return (MPJLambdaWrapperX<T>) ge(column, val1);
-        }
-        if (val2 != null) {
-            return (MPJLambdaWrapperX<T>) le(column, val2);
-        }
-        return this;
-    }
-
-    public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {
-        Object val1 = ArrayUtils.get(values, 0);
-        Object val2 = ArrayUtils.get(values, 1);
-        return betweenIfPresent(column, val1, val2);
-    }
-
-    // ========== 重写父类方法,方便链式调用 ==========
-
-    @Override
-    public <X> MPJLambdaWrapperX<T> eq(boolean condition, SFunction<X, ?> column, Object val) {
-        super.eq(condition, column, val);
-        return this;
-    }
-
-    @Override
-    public <X> MPJLambdaWrapperX<T> eq(SFunction<X, ?> column, Object val) {
-        super.eq(column, val);
-        return this;
-    }
-
-    @Override
-    public <X> MPJLambdaWrapperX<T> orderByDesc(SFunction<X, ?> column) {
-        //noinspection unchecked
-        super.orderByDesc(true, column);
-        return this;
-    }
-
-    @Override
-    public MPJLambdaWrapperX<T> last(String lastSql) {
-        super.last(lastSql);
-        return this;
-    }
-
-    @Override
-    public <X> MPJLambdaWrapperX<T> in(SFunction<X, ?> column, Collection<?> coll) {
-        super.in(column, coll);
-        return this;
-    }
-
-    @Override
-    public MPJLambdaWrapperX<T> selectAll(Class<?> clazz) {
-        super.selectAll(clazz);
-        return this;
-    }
-
-    @Override
-    public MPJLambdaWrapperX<T> selectAll(Class<?> clazz, String prefix) {
-        super.selectAll(clazz, prefix);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectAs(SFunction<S, ?> column, String alias) {
-        super.selectAs(column, alias);
-        return this;
-    }
-
-    @Override
-    public <E> MPJLambdaWrapperX<T> selectAs(String column, SFunction<E, ?> alias) {
-        super.selectAs(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectAs(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectAs(column, alias);
-        return this;
-    }
-
-    @Override
-    public <E, X> MPJLambdaWrapperX<T> selectAs(String index, SFunction<E, ?> column, SFunction<X, ?> alias) {
-        super.selectAs(index, column, alias);
-        return this;
-    }
-
-    @Override
-    public <E> MPJLambdaWrapperX<T> selectAsClass(Class<E> source, Class<?> tag) {
-        super.selectAsClass(source, tag);
-        return this;
-    }
-
-    @Override
-    public <E, F> MPJLambdaWrapperX<T> selectSub(Class<E> clazz, Consumer<MPJLambdaWrapper<E>> consumer, SFunction<F, ?> alias) {
-        super.selectSub(clazz, consumer, alias);
-        return this;
-    }
-
-    @Override
-    public <E, F> MPJLambdaWrapperX<T> selectSub(Class<E> clazz, String st, Consumer<MPJLambdaWrapper<E>> consumer, SFunction<F, ?> alias) {
-        super.selectSub(clazz, st, consumer, alias);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column) {
-        super.selectCount(column);
-        return this;
-    }
-
-    @Override
-    public MPJLambdaWrapperX<T> selectCount(Object column, String alias) {
-        super.selectCount(column, alias);
-        return this;
-    }
-
-    @Override
-    public <X> MPJLambdaWrapperX<T> selectCount(Object column, SFunction<X, ?> alias) {
-        super.selectCount(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column, String alias) {
-        super.selectCount(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectCount(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectCount(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column) {
-        super.selectSum(column);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column, String alias) {
-        super.selectSum(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectSum(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectSum(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column) {
-        super.selectMax(column);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column, String alias) {
-        super.selectMax(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectMax(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectMax(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column) {
-        super.selectMin(column);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column, String alias) {
-        super.selectMin(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectMin(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectMin(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column) {
-        super.selectAvg(column);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column, String alias) {
-        super.selectAvg(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectAvg(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectAvg(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column) {
-        super.selectLen(column);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column, String alias) {
-        super.selectLen(column, alias);
-        return this;
-    }
-
-    @Override
-    public <S, X> MPJLambdaWrapperX<T> selectLen(SFunction<S, ?> column, SFunction<X, ?> alias) {
-        super.selectLen(column, alias);
-        return this;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/QueryWrapperX.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/QueryWrapperX.java
deleted file mode 100644
index bf79bf5..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/query/QueryWrapperX.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package com.iailab.framework.mybatis.core.query;
-
-import cn.hutool.core.lang.Assert;
-import com.iailab.framework.mybatis.core.enums.SqlConstants;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import org.springframework.util.StringUtils;
-
-import java.util.Collection;
-
-/**
- * 拓展 MyBatis Plus QueryWrapper 类,主要增加如下功能:
- *
- * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
- *
- * @param <T> 数据类型
- */
-public class QueryWrapperX<T> extends QueryWrapper<T> {
-
-    public QueryWrapperX<T> likeIfPresent(String column, String val) {
-        if (StringUtils.hasText(val)) {
-            return (QueryWrapperX<T>) super.like(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> inIfPresent(String column, Collection<?> values) {
-        if (!CollectionUtils.isEmpty(values)) {
-            return (QueryWrapperX<T>) super.in(column, values);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> inIfPresent(String column, Object... values) {
-        if (!ArrayUtils.isEmpty(values)) {
-            return (QueryWrapperX<T>) super.in(column, values);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> eqIfPresent(String column, Object val) {
-        if (val != null) {
-            return (QueryWrapperX<T>) super.eq(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> neIfPresent(String column, Object val) {
-        if (val != null) {
-            return (QueryWrapperX<T>) super.ne(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> gtIfPresent(String column, Object val) {
-        if (val != null) {
-            return (QueryWrapperX<T>) super.gt(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> geIfPresent(String column, Object val) {
-        if (val != null) {
-            return (QueryWrapperX<T>) super.ge(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> ltIfPresent(String column, Object val) {
-        if (val != null) {
-            return (QueryWrapperX<T>) super.lt(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> leIfPresent(String column, Object val) {
-        if (val != null) {
-            return (QueryWrapperX<T>) super.le(column, val);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> betweenIfPresent(String column, Object val1, Object val2) {
-        if (val1 != null && val2 != null) {
-            return (QueryWrapperX<T>) super.between(column, val1, val2);
-        }
-        if (val1 != null) {
-            return (QueryWrapperX<T>) ge(column, val1);
-        }
-        if (val2 != null) {
-            return (QueryWrapperX<T>) le(column, val2);
-        }
-        return this;
-    }
-
-    public QueryWrapperX<T> betweenIfPresent(String column, Object[] values) {
-        if (values!= null && values.length != 0 && values[0] != null && values[1] != null) {
-            return (QueryWrapperX<T>) super.between(column, values[0], values[1]);
-        }
-        if (values!= null && values.length != 0 && values[0] != null) {
-            return (QueryWrapperX<T>) ge(column, values[0]);
-        }
-        if (values!= null && values.length != 0 && values[1] != null) {
-            return (QueryWrapperX<T>) le(column, values[1]);
-        }
-        return this;
-    }
-
-    // ========== 重写父类方法,方便链式调用 ==========
-
-    @Override
-    public QueryWrapperX<T> eq(boolean condition, String column, Object val) {
-        super.eq(condition, column, val);
-        return this;
-    }
-
-    @Override
-    public QueryWrapperX<T> eq(String column, Object val) {
-        super.eq(column, val);
-        return this;
-    }
-
-    @Override
-    public QueryWrapperX<T> orderByDesc(String column) {
-        super.orderByDesc(true, column);
-        return this;
-    }
-
-    @Override
-    public QueryWrapperX<T> last(String lastSql) {
-        super.last(lastSql);
-        return this;
-    }
-
-    @Override
-    public QueryWrapperX<T> in(String column, Collection<?> coll) {
-        super.in(column, coll);
-        return this;
-    }
-
-    /**
-     * 设置只返回最后一条
-     *
-     * TODO iailab:不是完美解,需要在思考下。如果使用多数据源,并且数据源是多种类型时,可能会存在问题:实现之返回一条的语法不同
-     *
-     * @return this
-     */
-    public QueryWrapperX<T> limitN(int n) {
-        Assert.notNull(SqlConstants.DB_TYPE, "获取不到数据库的类型");
-        switch (SqlConstants.DB_TYPE) {
-            case ORACLE:
-            case ORACLE_12C:
-                super.le("ROWNUM", n);
-                break;
-            case SQL_SERVER:
-            case SQL_SERVER2005:
-                super.select("TOP " + n + " *"); // 由于 SQL Server 是通过 SELECT TOP 1 实现限制一条,所以只好使用 * 查询剩余字段
-                break;
-            default:
-                super.last("LIMIT " + n);
-        }
-        return this;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/EncryptTypeHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/EncryptTypeHandler.java
deleted file mode 100644
index 57f92e2..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/EncryptTypeHandler.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.iailab.framework.mybatis.core.type;
-
-import cn.hutool.core.lang.Assert;
-import cn.hutool.crypto.SecureUtil;
-import cn.hutool.crypto.symmetric.AES;
-import cn.hutool.extra.spring.SpringUtil;
-import org.apache.ibatis.type.BaseTypeHandler;
-import org.apache.ibatis.type.JdbcType;
-
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-/**
- * 字段字段的 TypeHandler 实现类,基于 {@link cn.hutool.crypto.symmetric.AES} 实现
- * 可通过 jasypt.encryptor.password 配置项,设置密钥
- *
- * @author iailab
- */
-public class EncryptTypeHandler extends BaseTypeHandler<String> {
-
-    private static final String ENCRYPTOR_PROPERTY_NAME = "mybatis-plus.encryptor.password";
-
-    private static AES aes;
-
-    @Override
-    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
-        ps.setString(i, encrypt(parameter));
-    }
-
-    @Override
-    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
-        String value = rs.getString(columnName);
-        return decrypt(value);
-    }
-
-    @Override
-    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
-        String value = rs.getString(columnIndex);
-        return decrypt(value);
-    }
-
-    @Override
-    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
-        String value = cs.getString(columnIndex);
-        return decrypt(value);
-    }
-
-    private static String decrypt(String value) {
-        if (value == null) {
-            return null;
-        }
-        return getEncryptor().decryptStr(value);
-    }
-
-    public static String encrypt(String rawValue) {
-        if (rawValue == null) {
-            return null;
-        }
-        return getEncryptor().encryptBase64(rawValue);
-    }
-
-    private static AES getEncryptor() {
-        if (aes != null) {
-            return aes;
-        }
-        // 构建 AES
-        String password = SpringUtil.getProperty(ENCRYPTOR_PROPERTY_NAME);
-        Assert.notEmpty(password, "配置项({}) 不能为空", ENCRYPTOR_PROPERTY_NAME);
-        aes = SecureUtil.aes(password.getBytes());
-        return aes;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/IntegerListTypeHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/IntegerListTypeHandler.java
deleted file mode 100644
index 11041bc..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/IntegerListTypeHandler.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.iailab.framework.mybatis.core.type;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.util.string.StrUtils;
-import org.apache.ibatis.type.JdbcType;
-import org.apache.ibatis.type.MappedJdbcTypes;
-import org.apache.ibatis.type.MappedTypes;
-import org.apache.ibatis.type.TypeHandler;
-
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-
-/**
- * List<Integer> 的类型转换器实现类,对应数据库的 varchar 类型
- *
- * @author jason
- */
-@MappedJdbcTypes(JdbcType.VARCHAR)
-@MappedTypes(List.class)
-public class IntegerListTypeHandler implements TypeHandler<List<Integer>> {
-
-    private static final String COMMA = ",";
-
-    @Override
-    public void setParameter(PreparedStatement ps, int i, List<Integer> strings, JdbcType jdbcType) throws SQLException {
-        ps.setString(i, CollUtil.join(strings, COMMA));
-    }
-
-    @Override
-    public List<Integer> getResult(ResultSet rs, String columnName) throws SQLException {
-        String value = rs.getString(columnName);
-        return getResult(value);
-    }
-
-    @Override
-    public List<Integer> getResult(ResultSet rs, int columnIndex) throws SQLException {
-        String value = rs.getString(columnIndex);
-        return getResult(value);
-    }
-
-    @Override
-    public List<Integer> getResult(CallableStatement cs, int columnIndex) throws SQLException {
-        String value = cs.getString(columnIndex);
-        return getResult(value);
-    }
-
-    private List<Integer> getResult(String value) {
-        if (value == null) {
-            return null;
-        }
-        return StrUtils.splitToInteger(value, COMMA);
-    }
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/JsonLongSetTypeHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/JsonLongSetTypeHandler.java
deleted file mode 100644
index cce6ac8..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/JsonLongSetTypeHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-//package com.iailab.framework.mybatis.core.type;
-//
-//import com.iailab.framework.common.util.json.JsonUtils;
-//import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
-//import com.fasterxml.jackson.core.type.TypeReference;
-//
-//import java.util.Set;
-//
-///**
-// * 参考 {@link com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} 实现
-// * 在我们将字符串反序列化为 Set 并且泛型为 Long 时,如果每个元素的数值太小,会被处理成 Integer 类型,导致可能存在隐性的 BUG。
-// *
-// * 例如说哦,SysUserDO 的 postIds 属性
-// *
-// * @author iailab
-// */
-//public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler<Object> {
-//
-//    private static final TypeReference<Set<Long>> TYPE_REFERENCE = new TypeReference<Set<Long>>(){};
-//
-//    @Override
-//    protected Object parse(String json) {
-//        return JsonUtils.parseObject(json, TYPE_REFERENCE);
-//    }
-//
-//    @Override
-//    protected String toJson(Object obj) {
-//        return JsonUtils.toJsonString(obj);
-//    }
-//
-//}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/LongListTypeHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/LongListTypeHandler.java
deleted file mode 100644
index 4bbd179..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/LongListTypeHandler.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.iailab.framework.mybatis.core.type;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.util.string.StrUtils;
-import org.apache.ibatis.type.JdbcType;
-import org.apache.ibatis.type.MappedJdbcTypes;
-import org.apache.ibatis.type.MappedTypes;
-import org.apache.ibatis.type.TypeHandler;
-
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-
-/**
- * List<Long> 的类型转换器实现类,对应数据库的 varchar 类型
- *
- * @author iailab
- */
-@MappedJdbcTypes(JdbcType.VARCHAR)
-@MappedTypes(List.class)
-public class LongListTypeHandler implements TypeHandler<List<Long>> {
-
-    private static final String COMMA = ",";
-
-    @Override
-    public void setParameter(PreparedStatement ps, int i, List<Long> strings, JdbcType jdbcType) throws SQLException {
-        // 设置占位符
-        ps.setString(i, CollUtil.join(strings, COMMA));
-    }
-
-    @Override
-    public List<Long> getResult(ResultSet rs, String columnName) throws SQLException {
-        String value = rs.getString(columnName);
-        return getResult(value);
-    }
-
-    @Override
-    public List<Long> getResult(ResultSet rs, int columnIndex) throws SQLException {
-        String value = rs.getString(columnIndex);
-        return getResult(value);
-    }
-
-    @Override
-    public List<Long> getResult(CallableStatement cs, int columnIndex) throws SQLException {
-        String value = cs.getString(columnIndex);
-        return getResult(value);
-    }
-
-    private List<Long> getResult(String value) {
-        if (value == null) {
-            return null;
-        }
-        return StrUtils.splitToLong(value, COMMA);
-    }
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/StringListTypeHandler.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/StringListTypeHandler.java
deleted file mode 100644
index 024ffc0..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/type/StringListTypeHandler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.iailab.framework.mybatis.core.type;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.StrUtil;
-import org.apache.ibatis.type.JdbcType;
-import org.apache.ibatis.type.MappedJdbcTypes;
-import org.apache.ibatis.type.MappedTypes;
-import org.apache.ibatis.type.TypeHandler;
-
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.List;
-
-/**
- * List<String> 的类型转换器实现类,对应数据库的 varchar 类型
- *
- * @author 永不言败
- * @since 2022 3/23 12:50:15
- */
-@MappedJdbcTypes(JdbcType.VARCHAR)
-@MappedTypes(List.class)
-public class StringListTypeHandler implements TypeHandler<List<String>> {
-
-    private static final String COMMA = ",";
-
-    @Override
-    public void setParameter(PreparedStatement ps, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
-        // 设置占位符
-        ps.setString(i, CollUtil.join(strings, COMMA));
-    }
-
-    @Override
-    public List<String> getResult(ResultSet rs, String columnName) throws SQLException {
-        String value = rs.getString(columnName);
-        return getResult(value);
-    }
-
-    @Override
-    public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {
-        String value = rs.getString(columnIndex);
-        return getResult(value);
-    }
-
-    @Override
-    public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
-        String value = cs.getString(columnIndex);
-        return getResult(value);
-    }
-
-    private List<String> getResult(String value) {
-        if (value == null) {
-            return null;
-        }
-        return StrUtil.splitTrim(value, COMMA);
-    }
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/JdbcUtils.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/JdbcUtils.java
deleted file mode 100644
index 0275079..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/JdbcUtils.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.iailab.framework.mybatis.core.util;
-
-import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.iailab.framework.common.util.spring.SpringUtils;
-import com.iailab.framework.mybatis.core.enums.DbTypeEnum;
-
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
-/**
- * JDBC 工具类
- *
- * @author iailab
- */
-public class JdbcUtils {
-
-    /**
-     * 判断连接是否正确
-     *
-     * @param url      数据源连接
-     * @param username 账号
-     * @param password 密码
-     * @return 是否正确
-     */
-    public static boolean isConnectionOK(String url, String username, String password) {
-        try (Connection ignored = DriverManager.getConnection(url, username, password)) {
-            return true;
-        } catch (Exception ex) {
-            return false;
-        }
-    }
-
-    /**
-     * 获得 URL 对应的 DB 类型
-     *
-     * @param url URL
-     * @return DB 类型
-     */
-    public static DbType getDbType(String url) {
-        return com.baomidou.mybatisplus.extension.toolkit.JdbcUtils.getDbType(url);
-    }
-
-    /**
-     * 通过当前数据库连接获得对应的 DB 类型
-     *
-     * @return DB 类型
-     */
-    public static DbType getDbType() {
-        DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class);
-        DataSource dataSource = dynamicRoutingDataSource.determineDataSource();
-        try (Connection conn = dataSource.getConnection()) {
-            return DbTypeEnum.find(conn.getMetaData().getDatabaseProductName());
-        } catch (SQLException e) {
-            throw new IllegalArgumentException(e.getMessage());
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/MyBatisUtils.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/MyBatisUtils.java
deleted file mode 100644
index a8d8411..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/core/util/MyBatisUtils.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.iailab.framework.mybatis.core.util;
-
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.annotation.DbType;
-import com.baomidou.mybatisplus.core.metadata.OrderItem;
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.iailab.framework.common.pojo.PageParam;
-import com.iailab.framework.common.pojo.SortingField;
-import com.iailab.framework.mybatis.core.enums.DbTypeEnum;
-import net.sf.jsqlparser.expression.Alias;
-import net.sf.jsqlparser.schema.Column;
-import net.sf.jsqlparser.schema.Table;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * MyBatis 工具类
- */
-public class MyBatisUtils {
-
-    private static final String MYSQL_ESCAPE_CHARACTER = "`";
-
-    public static <T> Page<T> buildPage(PageParam pageParam) {
-        return buildPage(pageParam, null);
-    }
-
-    public static <T> Page<T> buildPage(PageParam pageParam, Collection<SortingField> sortingFields) {
-        // 页码 + 数量
-        Page<T> page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize());
-        // 排序字段
-        if (!CollectionUtil.isEmpty(sortingFields)) {
-            page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) ?
-                            OrderItem.asc(sortingField.getField()) : OrderItem.desc(sortingField.getField()))
-                    .collect(Collectors.toList()));
-        }
-        return page;
-    }
-
-    /**
-     * 将拦截器添加到链中
-     * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置
-     *
-     * @param interceptor 链
-     * @param inner       拦截器
-     * @param index       位置
-     */
-    public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) {
-        List<InnerInterceptor> inners = new ArrayList<>(interceptor.getInterceptors());
-        inners.add(index, inner);
-        interceptor.setInterceptors(inners);
-    }
-
-    /**
-     * 获得 Table 对应的表名
-     * <p>
-     * 兼容 MySQL 转义表名 `t_xxx`
-     *
-     * @param table 表
-     * @return 去除转移字符后的表名
-     */
-    public static String getTableName(Table table) {
-        String tableName = table.getName();
-        if (tableName.startsWith(MYSQL_ESCAPE_CHARACTER) && tableName.endsWith(MYSQL_ESCAPE_CHARACTER)) {
-            tableName = tableName.substring(1, tableName.length() - 1);
-        }
-        return tableName;
-    }
-
-    /**
-     * 构建 Column 对象
-     *
-     * @param tableName  表名
-     * @param tableAlias 别名
-     * @param column     字段名
-     * @return Column 对象
-     */
-    public static Column buildColumn(String tableName, Alias tableAlias, String column) {
-        if (tableAlias != null) {
-            tableName = tableAlias.getName();
-        }
-        return new Column(tableName + StringPool.DOT + column);
-    }
-
-    /**
-     * 跨数据库的 find_in_set 实现
-     *
-     * @param column 字段名称
-     * @param value  查询值(不带单引号)
-     * @return sql
-     */
-    public static String findInSet(String column, Object value) {
-        // 这里不用SqlConstants.DB_TYPE,因为它是使用 primary 数据源的 url 推断出来的类型
-        DbType dbType = JdbcUtils.getDbType();
-        return DbTypeEnum.getFindInSetTemplate(dbType)
-                .replace("#{column}", column)
-                .replace("#{value}", StrUtil.toString(value));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/interceptor/DataFilterInterceptor.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/interceptor/DataFilterInterceptor.java
deleted file mode 100644
index 8cf8a98..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/interceptor/DataFilterInterceptor.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.mybatis.interceptor;
-
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
-import net.sf.jsqlparser.JSQLParserException;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.StringValue;
-import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
-import net.sf.jsqlparser.parser.CCJSqlParserUtil;
-import net.sf.jsqlparser.statement.select.PlainSelect;
-import net.sf.jsqlparser.statement.select.Select;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.session.ResultHandler;
-import org.apache.ibatis.session.RowBounds;
-
-import java.util.Map;
-
-/**
- * 数据过滤
- *
- * @author Mark sunlightcs@gmail.com
- */
-public class DataFilterInterceptor implements InnerInterceptor {
-
-    @Override
-    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
-        DataScope scope = getDataScope(parameter);
-        // 不进行数据过滤
-        if(scope == null || StrUtil.isBlank(scope.getSqlFilter())){
-            return;
-        }
-
-        // 拼接新SQL
-        String buildSql = getSelect(boundSql.getSql(), scope);
-
-        // 重写SQL
-        PluginUtils.mpBoundSql(boundSql).sql(buildSql);
-    }
-
-    private DataScope getDataScope(Object parameter){
-        if (parameter == null){
-            return null;
-        }
-
-        // 判断参数里是否有DataScope对象
-        if (parameter instanceof Map) {
-            Map<?, ?> parameterMap = (Map<?, ?>) parameter;
-            for (Map.Entry entry : parameterMap.entrySet()) {
-                if (entry.getValue() != null && entry.getValue() instanceof DataScope) {
-                    return (DataScope) entry.getValue();
-                }
-            }
-        } else if (parameter instanceof DataScope) {
-            return (DataScope) parameter;
-        }
-
-        return null;
-    }
-
-    private String getSelect(String buildSql, DataScope scope){
-        try {
-            Select select = (Select) CCJSqlParserUtil.parse(buildSql);
-            PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
-
-            Expression expression = plainSelect.getWhere();
-            if(expression == null){
-                plainSelect.setWhere(new StringValue(scope.getSqlFilter()));
-            }else{
-                AndExpression andExpression =  new AndExpression(expression, new StringValue(scope.getSqlFilter()));
-                plainSelect.setWhere(andExpression);
-            }
-
-            return select.toString().replaceAll("'", "");
-        }catch (JSQLParserException e){
-            return buildSql;
-        }
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/interceptor/DataScope.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/interceptor/DataScope.java
deleted file mode 100644
index e9f2dcc..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/interceptor/DataScope.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.mybatis.interceptor;
-
-/**
- * 数据范围
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-public class DataScope {
-    private String sqlFilter;
-
-    public DataScope(String sqlFilter) {
-        this.sqlFilter = sqlFilter;
-    }
-
-    public String getSqlFilter() {
-        return sqlFilter;
-    }
-
-    public void setSqlFilter(String sqlFilter) {
-        this.sqlFilter = sqlFilter;
-    }
-
-    @Override
-    public String toString() {
-        return this.sqlFilter;
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/package-info.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/package-info.java
deleted file mode 100644
index bf8d7ef..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/mybatis/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 使用 MyBatis Plus 提升使用 MyBatis 的开发效率
- */
-package com.iailab.framework.mybatis;
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/config/IailabTranslateAutoConfiguration.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/config/IailabTranslateAutoConfiguration.java
deleted file mode 100644
index 55cfff1..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/config/IailabTranslateAutoConfiguration.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.iailab.framework.translate.config;
-
-import com.iailab.framework.translate.core.TranslateUtils;
-import com.fhs.trans.service.impl.TransService;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-
-@AutoConfiguration
-public class IailabTranslateAutoConfiguration {
-
-    @Bean
-    @SuppressWarnings({"InstantiationOfUtilityClass", "SpringJavaInjectionPointsAutowiringInspection"})
-    public TranslateUtils translateUtils(TransService transService) {
-        TranslateUtils.init(transService);
-        return new TranslateUtils();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/core/TranslateUtils.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/core/TranslateUtils.java
deleted file mode 100644
index 94f8b8b..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/core/TranslateUtils.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.translate.core;
-
-import cn.hutool.core.collection.CollUtil;
-import com.fhs.core.trans.vo.VO;
-import com.fhs.trans.service.impl.TransService;
-
-import java.util.List;
-
-/**
- * VO 数据翻译 Utils
- *
- * @author iailab
- */
-public class TranslateUtils {
-
-    private static TransService transService;
-
-    public static void init(TransService transService) {
-        TranslateUtils.transService = transService;
-    }
-
-    /**
-     * 数据翻译
-     *
-     * 使用场景:无法使用 @TransMethodResult 注解的场景,只能通过手动触发翻译
-     *
-     * @param data 数据
-     * @return 翻译结果
-     */
-    public static <T extends VO> List<T> translate(List<T> data) {
-        if (CollUtil.isNotEmpty((data))) {
-            transService.transBatch(data);
-        }
-        return data;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/package-info.java b/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/package-info.java
deleted file mode 100644
index 7378e0f..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/java/com/iailab/framework/translate/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 使用 Easy-Trans 提升使用 VO 数据翻译的开发效率
- */
-package com.iailab.framework.translate;
diff --git a/iailab-framework/iailab-common-mybatis/src/main/resources/META-INF/spring.factories b/iailab-framework/iailab-common-mybatis/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index a0149ea..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,2 +0,0 @@
-org.springframework.boot.env.EnvironmentPostProcessor=\
-  com.iailab.framework.mybatis.config.IdTypeEnvironmentPostProcessor
diff --git a/iailab-framework/iailab-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index c3f21ff..0000000
--- a/iailab-framework/iailab-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,3 +0,0 @@
-com.iailab.framework.datasource.config.IailabDataSourceAutoConfiguration
-com.iailab.framework.mybatis.config.IailabMybatisAutoConfiguration
-com.iailab.framework.translate.config.IailabTranslateAutoConfiguration
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-protection/pom.xml b/iailab-framework/iailab-common-protection/pom.xml
deleted file mode 100644
index 85ca482..0000000
--- a/iailab-framework/iailab-common-protection/pom.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-protection</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>服务保证,提供分布式锁、幂等、限流、熔断等等功能</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-web</artifactId>
-            <scope>provided</scope> <!-- 设置为 provided,只有限流、幂等使用到 -->
-        </dependency>
-
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-redis</artifactId>
-        </dependency>
-
-        <!-- 服务保障相关 -->
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/config/IailabIdempotentConfiguration.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/config/IailabIdempotentConfiguration.java
deleted file mode 100644
index 226645b..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/config/IailabIdempotentConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.idempotent.config;
-
-import com.iailab.framework.idempotent.core.aop.IdempotentAspect;
-import com.iailab.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.keyresolver.impl.UserIdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.redis.IdempotentRedisDAO;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import java.util.List;
-
-@AutoConfiguration(after = IailabRedisAutoConfiguration.class)
-public class IailabIdempotentConfiguration {
-
-    @Bean
-    public IdempotentAspect idempotentAspect(List<IdempotentKeyResolver> keyResolvers, IdempotentRedisDAO idempotentRedisDAO) {
-        return new IdempotentAspect(keyResolvers, idempotentRedisDAO);
-    }
-
-    @Bean
-    public IdempotentRedisDAO idempotentRedisDAO(StringRedisTemplate stringRedisTemplate) {
-        return new IdempotentRedisDAO(stringRedisTemplate);
-    }
-
-    // ========== 各种 IdempotentKeyResolver Bean ==========
-
-    @Bean
-    public DefaultIdempotentKeyResolver defaultIdempotentKeyResolver() {
-        return new DefaultIdempotentKeyResolver();
-    }
-
-    @Bean
-    public UserIdempotentKeyResolver userIdempotentKeyResolver() {
-        return new UserIdempotentKeyResolver();
-    }
-
-    @Bean
-    public ExpressionIdempotentKeyResolver expressionIdempotentKeyResolver() {
-        return new ExpressionIdempotentKeyResolver();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/annotation/Idempotent.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/annotation/Idempotent.java
deleted file mode 100644
index 8686c0a..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/annotation/Idempotent.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.iailab.framework.idempotent.core.annotation;
-
-import com.iailab.framework.idempotent.core.keyresolver.impl.DefaultIdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.keyresolver.impl.UserIdempotentKeyResolver;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 幂等注解
- *
- * @author iailab
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Idempotent {
-
-    /**
-     * 幂等的超时时间,默认为 1 秒
-     *
-     * 注意,如果执行时间超过它,请求还是会进来
-     */
-    int timeout() default 1;
-    /**
-     * 时间单位,默认为 SECONDS 秒
-     */
-    TimeUnit timeUnit() default TimeUnit.SECONDS;
-
-    /**
-     * 提示信息,正在执行中的提示
-     */
-    String message() default "重复请求,请稍后重试";
-
-    /**
-     * 使用的 Key 解析器
-     *
-     * @see DefaultIdempotentKeyResolver 全局级别
-     * @see UserIdempotentKeyResolver 用户级别
-     * @see ExpressionIdempotentKeyResolver 自定义表达式,通过 {@link #keyArg()} 计算
-     */
-    Class<? extends IdempotentKeyResolver> keyResolver() default DefaultIdempotentKeyResolver.class;
-    /**
-     * 使用的 Key 参数
-     */
-    String keyArg() default "";
-
-    /**
-     * 删除 Key,当发生异常时候
-     *
-     * 问题:为什么发生异常时,需要删除 Key 呢?
-     * 回答:发生异常时,说明业务发生错误,此时需要删除 Key,避免下次请求无法正常执行。
-     *
-     * 问题:为什么不搞 deleteWhenSuccess 执行成功时,需要删除 Key 呢?
-     * 回答:这种情况下,本质上是分布式锁,推荐使用 @Lock4j 注解
-     */
-    boolean deleteKeyWhenException() default true;
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/aop/IdempotentAspect.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/aop/IdempotentAspect.java
deleted file mode 100644
index 603f270..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/aop/IdempotentAspect.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.iailab.framework.idempotent.core.aop;
-
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.util.collection.CollectionUtils;
-import com.iailab.framework.idempotent.core.annotation.Idempotent;
-import com.iailab.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
-import com.iailab.framework.idempotent.core.redis.IdempotentRedisDAO;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.springframework.util.Assert;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 拦截声明了 {@link Idempotent} 注解的方法,实现幂等操作
- *
- * @author iailab
- */
-@Aspect
-@Slf4j
-public class IdempotentAspect {
-
-    /**
-     * IdempotentKeyResolver 集合
-     */
-    private final Map<Class<? extends IdempotentKeyResolver>, IdempotentKeyResolver> keyResolvers;
-
-    private final IdempotentRedisDAO idempotentRedisDAO;
-
-    public IdempotentAspect(List<IdempotentKeyResolver> keyResolvers, IdempotentRedisDAO idempotentRedisDAO) {
-        this.keyResolvers = CollectionUtils.convertMap(keyResolvers, IdempotentKeyResolver::getClass);
-        this.idempotentRedisDAO = idempotentRedisDAO;
-    }
-
-    @Around(value = "@annotation(idempotent)")
-    public Object aroundPointCut(ProceedingJoinPoint joinPoint, Idempotent idempotent) throws Throwable {
-        // 获得 IdempotentKeyResolver
-        IdempotentKeyResolver keyResolver = keyResolvers.get(idempotent.keyResolver());
-        Assert.notNull(keyResolver, "找不到对应的 IdempotentKeyResolver");
-        // 解析 Key
-        String key = keyResolver.resolver(joinPoint, idempotent);
-
-        // 1. 锁定 Key
-        boolean success = idempotentRedisDAO.setIfAbsent(key, idempotent.timeout(), idempotent.timeUnit());
-        // 锁定失败,抛出异常
-        if (!success) {
-            log.info("[aroundPointCut][方法({}) 参数({}) 存在重复请求]", joinPoint.getSignature().toString(), joinPoint.getArgs());
-            throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), idempotent.message());
-        }
-
-        // 2. 执行逻辑
-        try {
-            return joinPoint.proceed();
-        } catch (Throwable throwable) {
-            // 3. 异常时,删除 Key
-            // 参考美团 GTIS 思路:https://tech.meituan.com/2016/09/29/distributed-system-mutually-exclusive-idempotence-cerberus-gtis.html
-            if (idempotent.deleteKeyWhenException()) {
-                idempotentRedisDAO.delete(key);
-            }
-            throw throwable;
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java
deleted file mode 100644
index 503957a..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/IdempotentKeyResolver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.idempotent.core.keyresolver;
-
-import com.iailab.framework.idempotent.core.annotation.Idempotent;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * 幂等 Key 解析器接口
- *
- * @author iailab
- */
-public interface IdempotentKeyResolver {
-
-    /**
-     * 解析一个 Key
-     *
-     * @param idempotent 幂等注解
-     * @param joinPoint  AOP 切面
-     * @return Key
-     */
-    String resolver(JoinPoint joinPoint, Idempotent idempotent);
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java
deleted file mode 100644
index f9c5847..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/DefaultIdempotentKeyResolver.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.idempotent.core.keyresolver.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.SecureUtil;
-import com.iailab.framework.idempotent.core.annotation.Idempotent;
-import com.iailab.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * 默认(全局级别)幂等 Key 解析器,使用方法名 + 方法参数,组装成一个 Key
- *
- * 为了避免 Key 过长,使用 MD5 进行“压缩”
- *
- * @author iailab
- */
-public class DefaultIdempotentKeyResolver implements IdempotentKeyResolver {
-
-    @Override
-    public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
-        String methodName = joinPoint.getSignature().toString();
-        String argsStr = StrUtil.join(",", joinPoint.getArgs());
-        return SecureUtil.md5(methodName + argsStr);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java
deleted file mode 100644
index b1fe1b5..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.iailab.framework.idempotent.core.keyresolver.impl;
-
-import cn.hutool.core.util.ArrayUtil;
-import com.iailab.framework.idempotent.core.annotation.Idempotent;
-import com.iailab.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
-import org.springframework.core.ParameterNameDiscoverer;
-import org.springframework.expression.Expression;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
-
-import java.lang.reflect.Method;
-
-/**
- * 基于 Spring EL 表达式,
- *
- * @author iailab
- */
-public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver {
-
-    private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
-    private final ExpressionParser expressionParser = new SpelExpressionParser();
-
-    @Override
-    public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
-        // 获得被拦截方法参数名列表
-        Method method = getMethod(joinPoint);
-        Object[] args = joinPoint.getArgs();
-        String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);
-        // 准备 Spring EL 表达式解析的上下文
-        StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
-        if (ArrayUtil.isNotEmpty(parameterNames)) {
-            for (int i = 0; i < parameterNames.length; i++) {
-                evaluationContext.setVariable(parameterNames[i], args[i]);
-            }
-        }
-
-        // 解析参数
-        Expression expression = expressionParser.parseExpression(idempotent.keyArg());
-        return expression.getValue(evaluationContext, String.class);
-    }
-
-    private static Method getMethod(JoinPoint point) {
-        // 处理,声明在类上的情况
-        MethodSignature signature = (MethodSignature) point.getSignature();
-        Method method = signature.getMethod();
-        if (!method.getDeclaringClass().isInterface()) {
-            return method;
-        }
-
-        // 处理,声明在接口上的情况
-        try {
-            return point.getTarget().getClass().getDeclaredMethod(
-                    point.getSignature().getName(), method.getParameterTypes());
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/UserIdempotentKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/UserIdempotentKeyResolver.java
deleted file mode 100644
index 22e29bc..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/keyresolver/impl/UserIdempotentKeyResolver.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.idempotent.core.keyresolver.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.SecureUtil;
-import com.iailab.framework.idempotent.core.annotation.Idempotent;
-import com.iailab.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * 用户级别的幂等 Key 解析器,使用方法名 + 方法参数 + userId + userType,组装成一个 Key
- *
- * 为了避免 Key 过长,使用 MD5 进行“压缩”
- *
- * @author iailab
- */
-public class UserIdempotentKeyResolver implements IdempotentKeyResolver {
-
-    @Override
-    public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
-        String methodName = joinPoint.getSignature().toString();
-        String argsStr = StrUtil.join(",", joinPoint.getArgs());
-        Long userId = WebFrameworkUtils.getLoginUserId();
-        Integer userType = WebFrameworkUtils.getLoginUserType();
-        return SecureUtil.md5(methodName + argsStr + userId + userType);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/redis/IdempotentRedisDAO.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/redis/IdempotentRedisDAO.java
deleted file mode 100644
index 31b6b4b..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/core/redis/IdempotentRedisDAO.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.iailab.framework.idempotent.core.redis;
-
-import lombok.AllArgsConstructor;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 幂等 Redis DAO
- *
- * @author iailab
- */
-@AllArgsConstructor
-public class IdempotentRedisDAO {
-
-    /**
-     * 幂等操作
-     *
-     * KEY 格式:idempotent:%s // 参数为 uuid
-     * VALUE 格式:String
-     * 过期时间:不固定
-     */
-    private static final String IDEMPOTENT = "idempotent:%s";
-
-    private final StringRedisTemplate redisTemplate;
-
-    public Boolean setIfAbsent(String key, long timeout, TimeUnit timeUnit) {
-        String redisKey = formatKey(key);
-        return redisTemplate.opsForValue().setIfAbsent(redisKey, "", timeout, timeUnit);
-    }
-
-    public void delete(String key) {
-        String redisKey = formatKey(key);
-        redisTemplate.delete(redisKey);
-    }
-
-    private static String formatKey(String key) {
-        return String.format(IDEMPOTENT, key);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/package-info.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/package-info.java
deleted file mode 100644
index 052e4b7..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/idempotent/package-info.java
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * 幂等组件,参考 https://github.com/it4alla/idempotent 项目实现
- * 实现原理是,相同参数的方法,一段时间内,有且仅能执行一次。通过这样的方式,保证幂等性。
- *
- * 使用场景:例如说,用户快速的双击了某个按钮,前端没有禁用该按钮,导致发送了两次重复的请求。
- *
- * 和 it4alla/idempotent 组件的差异点,主要体现在两点:
- *  1. 我们去掉了 @Idempotent 注解的 delKey 属性。原因是,本质上 delKey 为 true 时,实现的是分布式锁的能力
- * 此时,我们偏向使用 Lock4j 组件。原则上,一个组件只提供一种单一的能力。
- *  2. 考虑到组件的通用性,我们并未像 it4alla/idempotent 组件一样使用 Redisson RMap 结构,而是直接使用 Redis 的 String 数据格式。
- */
-package com.iailab.framework.idempotent;
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/config/IailabLock4jConfiguration.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/config/IailabLock4jConfiguration.java
deleted file mode 100644
index 4e72e65..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/config/IailabLock4jConfiguration.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.iailab.framework.lock4j.config;
-
-import com.iailab.framework.lock4j.core.DefaultLockFailureStrategy;
-import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.context.annotation.Bean;
-
-@AutoConfiguration(before = LockAutoConfiguration.class)
-@ConditionalOnClass(name = "com.baomidou.lock.annotation.Lock4j")
-public class IailabLock4jConfiguration {
-
-    @Bean
-    public DefaultLockFailureStrategy lockFailureStrategy() {
-        return new DefaultLockFailureStrategy();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/core/DefaultLockFailureStrategy.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/core/DefaultLockFailureStrategy.java
deleted file mode 100644
index d2187a7..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/core/DefaultLockFailureStrategy.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.framework.lock4j.core;
-
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.baomidou.lock.LockFailureStrategy;
-import lombok.extern.slf4j.Slf4j;
-
-import java.lang.reflect.Method;
-
-/**
- * 自定义获取锁失败策略,抛出 {@link ServiceException} 异常
- */
-@Slf4j
-public class DefaultLockFailureStrategy implements LockFailureStrategy {
-
-    @Override
-    public void onLockFailure(String key, Method method, Object[] arguments) {
-        log.debug("[onLockFailure][线程:{} 获取锁失败,key:{} 获取失败:{} ]", Thread.currentThread().getName(), key, arguments);
-        throw new ServiceException(GlobalErrorCodeConstants.LOCKED);
-    }
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/core/Lock4jRedisKeyConstants.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/core/Lock4jRedisKeyConstants.java
deleted file mode 100644
index fbb076f..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/core/Lock4jRedisKeyConstants.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.framework.lock4j.core;
-
-/**
- * Lock4j Redis Key 枚举类
- *
- * @author iailab
- */
-public interface Lock4jRedisKeyConstants {
-
-    /**
-     * 分布式锁
-     *
-     * KEY 格式:lock4j:%s // 参数来自 DefaultLockKeyBuilder 类
-     * VALUE 数据格式:HASH // RLock.class:Redisson 的 Lock 锁,使用 Hash 数据结构
-     * 过期时间:不固定
-     */
-    String LOCK4J = "lock4j:%s";
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/package-info.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/package-info.java
deleted file mode 100644
index 3016962..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/lock4j/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 分布式锁组件,使用 https://gitee.com/baomidou/lock4j 开源项目
- */
-package com.iailab.framework.lock4j;
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/config/IailabRateLimiterConfiguration.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/config/IailabRateLimiterConfiguration.java
deleted file mode 100644
index 4ce5009..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/config/IailabRateLimiterConfiguration.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.iailab.framework.ratelimiter.config;
-
-import com.iailab.framework.ratelimiter.core.aop.RateLimiterAspect;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import com.iailab.framework.ratelimiter.core.keyresolver.impl.*;
-import com.iailab.framework.ratelimiter.core.redis.RateLimiterRedisDAO;
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import org.redisson.api.RedissonClient;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-
-import java.util.List;
-
-@AutoConfiguration(after = IailabRedisAutoConfiguration.class)
-public class IailabRateLimiterConfiguration {
-
-    @Bean
-    public RateLimiterAspect rateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {
-        return new RateLimiterAspect(keyResolvers, rateLimiterRedisDAO);
-    }
-
-    @Bean
-    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
-    public RateLimiterRedisDAO rateLimiterRedisDAO(RedissonClient redissonClient) {
-        return new RateLimiterRedisDAO(redissonClient);
-    }
-
-    // ========== 各种 RateLimiterRedisDAO Bean ==========
-
-    @Bean
-    public DefaultRateLimiterKeyResolver defaultRateLimiterKeyResolver() {
-        return new DefaultRateLimiterKeyResolver();
-    }
-
-    @Bean
-    public UserRateLimiterKeyResolver userRateLimiterKeyResolver() {
-        return new UserRateLimiterKeyResolver();
-    }
-
-    @Bean
-    public ClientIpRateLimiterKeyResolver clientIpRateLimiterKeyResolver() {
-        return new ClientIpRateLimiterKeyResolver();
-    }
-
-    @Bean
-    public ServerNodeRateLimiterKeyResolver serverNodeRateLimiterKeyResolver() {
-        return new ServerNodeRateLimiterKeyResolver();
-    }
-
-    @Bean
-    public ExpressionRateLimiterKeyResolver expressionRateLimiterKeyResolver() {
-        return new ExpressionRateLimiterKeyResolver();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/annotation/RateLimiter.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/annotation/RateLimiter.java
deleted file mode 100644
index 1be2263..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/annotation/RateLimiter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.iailab.framework.ratelimiter.core.annotation;
-
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import com.iailab.framework.ratelimiter.core.keyresolver.impl.ClientIpRateLimiterKeyResolver;
-import com.iailab.framework.ratelimiter.core.keyresolver.impl.DefaultRateLimiterKeyResolver;
-import com.iailab.framework.ratelimiter.core.keyresolver.impl.ServerNodeRateLimiterKeyResolver;
-import com.iailab.framework.ratelimiter.core.keyresolver.impl.UserRateLimiterKeyResolver;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 限流注解
- *
- * @author iailab
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface RateLimiter {
-
-    /**
-     * 限流的时间,默认为 1 秒
-     */
-    int time() default 1;
-    /**
-     * 时间单位,默认为 SECONDS 秒
-     */
-    TimeUnit timeUnit() default TimeUnit.SECONDS;
-
-    /**
-     * 限流次数
-     */
-    int count() default 100;
-
-    /**
-     * 提示信息,请求过快的提示
-     *
-     * @see GlobalErrorCodeConstants#TOO_MANY_REQUESTS
-     */
-    String message() default ""; // 为空时,使用 TOO_MANY_REQUESTS 错误提示
-
-    /**
-     * 使用的 Key 解析器
-     *
-     * @see DefaultRateLimiterKeyResolver 全局级别
-     * @see UserRateLimiterKeyResolver 用户 ID 级别
-     * @see ClientIpRateLimiterKeyResolver 用户 IP 级别
-     * @see ServerNodeRateLimiterKeyResolver 服务器 Node 级别
-     * @see ExpressionIdempotentKeyResolver 自定义表达式,通过 {@link #keyArg()} 计算
-     */
-    Class<? extends RateLimiterKeyResolver> keyResolver() default DefaultRateLimiterKeyResolver.class;
-    /**
-     * 使用的 Key 参数
-     */
-    String keyArg() default "";
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/aop/RateLimiterAspect.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/aop/RateLimiterAspect.java
deleted file mode 100644
index 1ca33d2..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/aop/RateLimiterAspect.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.framework.ratelimiter.core.aop;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.util.collection.CollectionUtils;
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import com.iailab.framework.ratelimiter.core.redis.RateLimiterRedisDAO;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.springframework.util.Assert;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 拦截声明了 {@link RateLimiter} 注解的方法,实现限流操作
- *
- * @author iailab
- */
-@Aspect
-@Slf4j
-public class RateLimiterAspect {
-
-    /**
-     * RateLimiterKeyResolver 集合
-     */
-    private final Map<Class<? extends RateLimiterKeyResolver>, RateLimiterKeyResolver> keyResolvers;
-
-    private final RateLimiterRedisDAO rateLimiterRedisDAO;
-
-    public RateLimiterAspect(List<RateLimiterKeyResolver> keyResolvers, RateLimiterRedisDAO rateLimiterRedisDAO) {
-        this.keyResolvers = CollectionUtils.convertMap(keyResolvers, RateLimiterKeyResolver::getClass);
-        this.rateLimiterRedisDAO = rateLimiterRedisDAO;
-    }
-
-    @Before("@annotation(rateLimiter)")
-    public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {
-        // 获得 IdempotentKeyResolver 对象
-        RateLimiterKeyResolver keyResolver = keyResolvers.get(rateLimiter.keyResolver());
-        Assert.notNull(keyResolver, "找不到对应的 RateLimiterKeyResolver");
-        // 解析 Key
-        String key = keyResolver.resolver(joinPoint, rateLimiter);
-
-        // 获取 1 次限流
-        boolean success = rateLimiterRedisDAO.tryAcquire(key,
-                rateLimiter.count(), rateLimiter.time(), rateLimiter.timeUnit());
-        if (!success) {
-            log.info("[beforePointCut][方法({}) 参数({}) 请求过于频繁]", joinPoint.getSignature().toString(), joinPoint.getArgs());
-            String message = StrUtil.blankToDefault(rateLimiter.message(),
-                    GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getMsg());
-            throw new ServiceException(GlobalErrorCodeConstants.TOO_MANY_REQUESTS.getCode(), message);
-        }
-    }
-
-}
-
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/RateLimiterKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/RateLimiterKeyResolver.java
deleted file mode 100644
index e72d70d..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/RateLimiterKeyResolver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.ratelimiter.core.keyresolver;
-
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * 限流 Key 解析器接口
- *
- * @author iailab
- */
-public interface RateLimiterKeyResolver {
-
-    /**
-     * 解析一个 Key
-     *
-     * @param rateLimiter 限流注解
-     * @param joinPoint  AOP 切面
-     * @return Key
-     */
-    String resolver(JoinPoint joinPoint, RateLimiter rateLimiter);
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ClientIpRateLimiterKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ClientIpRateLimiterKeyResolver.java
deleted file mode 100644
index 2e9be94..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ClientIpRateLimiterKeyResolver.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.ratelimiter.core.keyresolver.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.SecureUtil;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * IP 级别的限流 Key 解析器,使用方法名 + 方法参数 + IP,组装成一个 Key
- *
- * 为了避免 Key 过长,使用 MD5 进行“压缩”
- *
- * @author iailab
- */
-public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver {
-
-    @Override
-    public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
-        String methodName = joinPoint.getSignature().toString();
-        String argsStr = StrUtil.join(",", joinPoint.getArgs());
-        String clientIp = ServletUtils.getClientIP();
-        return SecureUtil.md5(methodName + argsStr + clientIp);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/DefaultRateLimiterKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/DefaultRateLimiterKeyResolver.java
deleted file mode 100644
index 1b3af97..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/DefaultRateLimiterKeyResolver.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.ratelimiter.core.keyresolver.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.SecureUtil;
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * 默认(全局级别)限流 Key 解析器,使用方法名 + 方法参数,组装成一个 Key
- *
- * 为了避免 Key 过长,使用 MD5 进行“压缩”
- *
- * @author iailab
- */
-public class DefaultRateLimiterKeyResolver implements RateLimiterKeyResolver {
-
-    @Override
-    public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
-        String methodName = joinPoint.getSignature().toString();
-        String argsStr = StrUtil.join(",", joinPoint.getArgs());
-        return SecureUtil.md5(methodName + argsStr);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ExpressionRateLimiterKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ExpressionRateLimiterKeyResolver.java
deleted file mode 100644
index 813daa3..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ExpressionRateLimiterKeyResolver.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.iailab.framework.ratelimiter.core.keyresolver.impl;
-
-import cn.hutool.core.util.ArrayUtil;
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.springframework.core.DefaultParameterNameDiscoverer;
-import org.springframework.core.ParameterNameDiscoverer;
-import org.springframework.expression.Expression;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
-
-import java.lang.reflect.Method;
-
-/**
- * 基于 Spring EL 表达式的 {@link RateLimiterKeyResolver} 实现类
- *
- * @author iailab
- */
-public class ExpressionRateLimiterKeyResolver implements RateLimiterKeyResolver {
-
-    private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
-
-    private final ExpressionParser expressionParser = new SpelExpressionParser();
-
-    @Override
-    public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
-        // 获得被拦截方法参数名列表
-        Method method = getMethod(joinPoint);
-        Object[] args = joinPoint.getArgs();
-        String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);
-        // 准备 Spring EL 表达式解析的上下文
-        StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
-        if (ArrayUtil.isNotEmpty(parameterNames)) {
-            for (int i = 0; i < parameterNames.length; i++) {
-                evaluationContext.setVariable(parameterNames[i], args[i]);
-            }
-        }
-
-        // 解析参数
-        Expression expression = expressionParser.parseExpression(rateLimiter.keyArg());
-        return expression.getValue(evaluationContext, String.class);
-    }
-
-    private static Method getMethod(JoinPoint point) {
-        // 处理,声明在类上的情况
-        MethodSignature signature = (MethodSignature) point.getSignature();
-        Method method = signature.getMethod();
-        if (!method.getDeclaringClass().isInterface()) {
-            return method;
-        }
-
-        // 处理,声明在接口上的情况
-        try {
-            return point.getTarget().getClass().getDeclaredMethod(
-                    point.getSignature().getName(), method.getParameterTypes());
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ServerNodeRateLimiterKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ServerNodeRateLimiterKeyResolver.java
deleted file mode 100644
index 16775f1..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/ServerNodeRateLimiterKeyResolver.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.ratelimiter.core.keyresolver.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.SecureUtil;
-import cn.hutool.system.SystemUtil;
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * Server 节点级别的限流 Key 解析器,使用方法名 + 方法参数 + IP,组装成一个 Key
- *
- * 为了避免 Key 过长,使用 MD5 进行“压缩”
- *
- * @author iailab
- */
-public class ServerNodeRateLimiterKeyResolver implements RateLimiterKeyResolver {
-
-    @Override
-    public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
-        String methodName = joinPoint.getSignature().toString();
-        String argsStr = StrUtil.join(",", joinPoint.getArgs());
-        String serverNode = String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
-        return SecureUtil.md5(methodName + argsStr + serverNode);
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/UserRateLimiterKeyResolver.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/UserRateLimiterKeyResolver.java
deleted file mode 100644
index 9fed5cc..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/keyresolver/impl/UserRateLimiterKeyResolver.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.ratelimiter.core.keyresolver.impl;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.SecureUtil;
-import com.iailab.framework.ratelimiter.core.annotation.RateLimiter;
-import com.iailab.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.aspectj.lang.JoinPoint;
-
-/**
- * 用户级别的限流 Key 解析器,使用方法名 + 方法参数 + userId + userType,组装成一个 Key
- *
- * 为了避免 Key 过长,使用 MD5 进行“压缩”
- *
- * @author iailab
- */
-public class UserRateLimiterKeyResolver implements RateLimiterKeyResolver {
-
-    @Override
-    public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
-        String methodName = joinPoint.getSignature().toString();
-        String argsStr = StrUtil.join(",", joinPoint.getArgs());
-        Long userId = WebFrameworkUtils.getLoginUserId();
-        Integer userType = WebFrameworkUtils.getLoginUserType();
-        return SecureUtil.md5(methodName + argsStr + userId + userType);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java
deleted file mode 100644
index 5a113c3..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.framework.ratelimiter.core.redis;
-
-import lombok.AllArgsConstructor;
-import org.redisson.api.*;
-
-import java.util.Objects;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 限流 Redis DAO
- *
- * @author iailab
- */
-@AllArgsConstructor
-public class RateLimiterRedisDAO {
-
-    /**
-     * 限流操作
-     *
-     * KEY 格式:rate_limiter:%s // 参数为 uuid
-     * VALUE 格式:String
-     * 过期时间:不固定
-     */
-    private static final String RATE_LIMITER = "rate_limiter:%s";
-
-    private final RedissonClient redissonClient;
-
-    public Boolean tryAcquire(String key, int count, int time, TimeUnit timeUnit) {
-        // 1. 获得 RRateLimiter,并设置 rate 速率
-        RRateLimiter rateLimiter = getRRateLimiter(key, count, time, timeUnit);
-        // 2. 尝试获取 1 个
-        return rateLimiter.tryAcquire();
-    }
-
-    private static String formatKey(String key) {
-        return String.format(RATE_LIMITER, key);
-    }
-
-    private RRateLimiter getRRateLimiter(String key, long count, int time, TimeUnit timeUnit) {
-        String redisKey = formatKey(key);
-        RRateLimiter rateLimiter = redissonClient.getRateLimiter(redisKey);
-        long rateInterval = timeUnit.toSeconds(time);
-        // 1. 如果不存在,设置 rate 速率
-        RateLimiterConfig config = rateLimiter.getConfig();
-        if (config == null) {
-            rateLimiter.trySetRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
-            return rateLimiter;
-        }
-        // 2. 如果存在,并且配置相同,则直接返回
-        if (config.getRateType() == RateType.OVERALL
-                && Objects.equals(config.getRate(), count)
-                && Objects.equals(config.getRateInterval(), TimeUnit.SECONDS.toMillis(rateInterval))) {
-            return rateLimiter;
-        }
-        // 3. 如果存在,并且配置不同,则进行新建
-        rateLimiter.setRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
-        return rateLimiter;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/package-info.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/package-info.java
deleted file mode 100644
index fc519ac..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/ratelimiter/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 限流组件,基于 Redisson {@link org.redisson.api.RRateLimiter} 限流实现
- */
-package com.iailab.framework.ratelimiter;
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/config/IailabApiSignatureAutoConfiguration.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/config/IailabApiSignatureAutoConfiguration.java
deleted file mode 100644
index a036906..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/config/IailabApiSignatureAutoConfiguration.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.signature.config;
-
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import com.iailab.framework.signature.core.aop.ApiSignatureAspect;
-import com.iailab.framework.signature.core.redis.ApiSignatureRedisDAO;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-/**
- * HTTP API 签名的自动配置类
- *
- * @author Zhougang
- */
-@AutoConfiguration(after = IailabRedisAutoConfiguration.class)
-public class IailabApiSignatureAutoConfiguration {
-
-    @Bean
-    public ApiSignatureAspect signatureAspect(ApiSignatureRedisDAO signatureRedisDAO) {
-        return new ApiSignatureAspect(signatureRedisDAO);
-    }
-
-    @Bean
-    public ApiSignatureRedisDAO signatureRedisDAO(StringRedisTemplate stringRedisTemplate) {
-        return new ApiSignatureRedisDAO(stringRedisTemplate);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/annotation/ApiSignature.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/annotation/ApiSignature.java
deleted file mode 100644
index c0a263b..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/annotation/ApiSignature.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.iailab.framework.signature.core.annotation;
-
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-
-import java.lang.annotation.*;
-import java.util.concurrent.TimeUnit;
-
-
-/**
- * HTTP API 签名注解
- *
- * @author Zhougang
- */
-@Inherited
-@Documented
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ApiSignature {
-
-    /**
-     * 同一个请求多长时间内有效 默认 60 秒
-     */
-    int timeout() default 60;
-
-    /**
-     * 时间单位,默认为 SECONDS 秒
-     */
-    TimeUnit timeUnit() default TimeUnit.SECONDS;
-
-    // ========================== 签名参数 ==========================
-
-    /**
-     * 提示信息,签名失败的提示
-     *
-     * @see GlobalErrorCodeConstants#BAD_REQUEST
-     */
-    String message() default "签名不正确"; // 为空时,使用 BAD_REQUEST 错误提示
-
-    /**
-     * 签名字段:appId 应用ID
-     */
-    String appId() default "appId";
-
-    /**
-     * 签名字段:timestamp 时间戳
-     */
-    String timestamp() default "timestamp";
-
-    /**
-     * 签名字段:nonce 随机数,10 位以上
-     */
-    String nonce() default "nonce";
-
-    /**
-     * sign 客户端签名
-     */
-    String sign() default "sign";
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/aop/ApiSignatureAspect.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/aop/ApiSignatureAspect.java
deleted file mode 100644
index 716f0de..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/aop/ApiSignatureAspect.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package com.iailab.framework.signature.core.aop;
-
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ObjUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.digest.DigestUtil;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.signature.core.annotation.ApiSignature;
-import com.iailab.framework.signature.core.redis.ApiSignatureRedisDAO;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-
-/**
- * 拦截声明了 {@link ApiSignature} 注解的方法,实现签名
- *
- * @author Zhougang
- */
-@Aspect
-@Slf4j
-@AllArgsConstructor
-public class ApiSignatureAspect {
-
-    private final ApiSignatureRedisDAO signatureRedisDAO;
-
-    @Before("@annotation(signature)")
-    public void beforePointCut(JoinPoint joinPoint, ApiSignature signature) {
-        // 1. 验证通过,直接结束
-        if (verifySignature(signature, Objects.requireNonNull(ServletUtils.getRequest()))) {
-            return;
-        }
-
-        // 2. 验证不通过,抛出异常
-        log.error("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(),
-                joinPoint.getArgs());
-        throw new ServiceException(BAD_REQUEST.getCode(),
-                StrUtil.blankToDefault(signature.message(), BAD_REQUEST.getMsg()));
-    }
-
-    public boolean verifySignature(ApiSignature signature, HttpServletRequest request) {
-        // 1.1 校验 Header
-        if (!verifyHeaders(signature, request)) {
-            return false;
-        }
-        // 1.2 校验 appId 是否能获取到对应的 appSecret
-        String appId = request.getHeader(signature.appId());
-        String appSecret = signatureRedisDAO.getAppSecret(appId);
-        Assert.notNull(appSecret, "[appId({})] 找不到对应的 appSecret", appId);
-
-        // 2. 校验签名【重要!】
-        String clientSignature = request.getHeader(signature.sign()); // 客户端签名
-        String serverSignatureString = buildSignatureString(signature, request, appSecret); // 服务端签名字符串
-        String serverSignature = DigestUtil.sha256Hex(serverSignatureString); // 服务端签名
-        if (ObjUtil.notEqual(clientSignature, serverSignature)) {
-            return false;
-        }
-
-        // 3. 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 )
-        String nonce = request.getHeader(signature.nonce());
-        signatureRedisDAO.setNonce(nonce, signature.timeout() * 2, signature.timeUnit());
-        return true;
-    }
-
-    /**
-     * 校验请求头加签参数
-     *
-     * 1. appId 是否为空
-     * 2. timestamp 是否为空,请求是否已经超时,默认 10 分钟
-     * 3. nonce 是否为空,随机数是否 10 位以上,是否在规定时间内已经访问过了
-     * 4. sign 是否为空
-     *
-     * @param signature signature
-     * @param request   request
-     * @return 是否校验 Header 通过
-     */
-    private boolean verifyHeaders(ApiSignature signature, HttpServletRequest request) {
-        // 1. 非空校验
-        String appId = request.getHeader(signature.appId());
-        if (StrUtil.isBlank(appId)) {
-            return false;
-        }
-        String timestamp = request.getHeader(signature.timestamp());
-        if (StrUtil.isBlank(timestamp)) {
-            return false;
-        }
-        String nonce = request.getHeader(signature.nonce());
-        if (StrUtil.length(nonce) < 10) {
-            return false;
-        }
-        String sign = request.getHeader(signature.sign());
-        if (StrUtil.isBlank(sign)) {
-            return false;
-        }
-
-        // 2. 检查 timestamp 是否超出允许的范围 (重点一:此处需要取绝对值)
-        long expireTime = signature.timeUnit().toMillis(signature.timeout());
-        long requestTimestamp = Long.parseLong(timestamp);
-        long timestampDisparity = Math.abs(System.currentTimeMillis() - requestTimestamp);
-        if (timestampDisparity > expireTime) {
-            return false;
-        }
-
-        // 3. 检查 nonce 是否存在,有且仅能使用一次
-        return signatureRedisDAO.getNonce(nonce) == null;
-    }
-
-    /**
-     * 构建签名字符串
-     *
-     * 格式为 = 请求参数 + 请求体 + 请求头 + 密钥
-     *
-     * @param signature signature
-     * @param request   request
-     * @param appSecret appSecret
-     * @return 签名字符串
-     */
-    private String buildSignatureString(ApiSignature signature, HttpServletRequest request, String appSecret) {
-        SortedMap<String, String> parameterMap = getRequestParameterMap(request); // 请求头
-        SortedMap<String, String> headerMap = getRequestHeaderMap(signature, request); // 请求参数
-        String requestBody = StrUtil.nullToDefault(ServletUtils.getBody(request), ""); // 请求体
-        return MapUtil.join(parameterMap, "&", "=")
-                + requestBody
-                + MapUtil.join(headerMap, "&", "=")
-                + appSecret;
-    }
-
-    /**
-     * 获取请求头加签参数 Map
-     *
-     * @param request 请求
-     * @param signature 签名注解
-     * @return signature params
-     */
-    private static SortedMap<String, String> getRequestHeaderMap(ApiSignature signature, HttpServletRequest request) {
-        SortedMap<String, String> sortedMap = new TreeMap<>();
-        sortedMap.put(signature.appId(), request.getHeader(signature.appId()));
-        sortedMap.put(signature.timestamp(), request.getHeader(signature.timestamp()));
-        sortedMap.put(signature.nonce(), request.getHeader(signature.nonce()));
-        return sortedMap;
-    }
-
-    /**
-     * 获取请求参数 Map
-     *
-     * @param request 请求
-     * @return queryParams
-     */
-    private static SortedMap<String, String> getRequestParameterMap(HttpServletRequest request) {
-        SortedMap<String, String> sortedMap = new TreeMap<>();
-        for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
-            sortedMap.put(entry.getKey(), entry.getValue()[0]);
-        }
-        return sortedMap;
-    }
-
-}
-
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/redis/ApiSignatureRedisDAO.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/redis/ApiSignatureRedisDAO.java
deleted file mode 100644
index b6c8c8e..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/core/redis/ApiSignatureRedisDAO.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.iailab.framework.signature.core.redis;
-
-import lombok.AllArgsConstructor;
-import org.springframework.data.redis.core.StringRedisTemplate;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * HTTP API 签名 Redis DAO
- *
- * @author Zhougang
- */
-@AllArgsConstructor
-public class ApiSignatureRedisDAO {
-
-    private final StringRedisTemplate stringRedisTemplate;
-
-    /**
-     * 验签随机数
-     *
-     * KEY 格式:signature_nonce:%s // 参数为 随机数
-     * VALUE 格式:String
-     * 过期时间:不固定
-     */
-    private static final String SIGNATURE_NONCE = "api_signature_nonce:%s";
-
-    /**
-     * 签名密钥
-     *
-     * HASH 结构
-     * KEY 格式:%s // 参数为 appid
-     * VALUE 格式:String
-     * 过期时间:永不过期(预加载到 Redis)
-     */
-    private static final String SIGNATURE_APPID = "api_signature_app";
-
-    // ========== 验签随机数 ==========
-
-    public String getNonce(String nonce) {
-        return stringRedisTemplate.opsForValue().get(formatNonceKey(nonce));
-    }
-
-    public void setNonce(String nonce, int time, TimeUnit timeUnit) {
-        stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), "", time, timeUnit);
-    }
-
-    private static String formatNonceKey(String key) {
-        return String.format(SIGNATURE_NONCE, key);
-    }
-
-    // ========== 签名密钥 ==========
-
-    public String getAppSecret(String appId) {
-        return (String) stringRedisTemplate.opsForHash().get(SIGNATURE_APPID, appId);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/package-info.java b/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/package-info.java
deleted file mode 100644
index 1f5f8ac..0000000
--- a/iailab-framework/iailab-common-protection/src/main/java/com/iailab/framework/signature/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * HTTP API 签名,校验安全性
- *
- * @see <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3>微信支付 —— 安全规范</a>
- */
-package com.iailab.framework.signature;
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 85259d2..0000000
--- a/iailab-framework/iailab-common-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,3 +0,0 @@
-com.iailab.framework.idempotent.config.IailabIdempotentConfiguration
-com.iailab.framework.lock4j.config.IailabLock4jConfiguration
-com.iailab.framework.ratelimiter.config.IailabRateLimiterConfiguration
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-protection/src/test/java/com/iailab/framework/signature/core/ApiSignatureTest.java b/iailab-framework/iailab-common-protection/src/test/java/com/iailab/framework/signature/core/ApiSignatureTest.java
deleted file mode 100644
index 8c94e79..0000000
--- a/iailab-framework/iailab-common-protection/src/test/java/com/iailab/framework/signature/core/ApiSignatureTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.iailab.framework.signature.core;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.crypto.digest.DigestUtil;
-import com.iailab.framework.signature.core.annotation.ApiSignature;
-import com.iailab.framework.signature.core.aop.ApiSignatureAspect;
-import com.iailab.framework.signature.core.redis.ApiSignatureRedisDAO;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-/**
- * {@link ApiSignatureTest} 的单元测试
- */
-@ExtendWith(MockitoExtension.class)
-public class ApiSignatureTest {
-
-    @InjectMocks
-    private ApiSignatureAspect apiSignatureAspect;
-
-    @Mock
-    private ApiSignatureRedisDAO signatureRedisDAO;
-
-    @Test
-    public void testSignatureGet() throws IOException {
-        // 搞一个签名
-        Long timestamp = System.currentTimeMillis();
-        String nonce = IdUtil.randomUUID();
-        String appId = "xxxxxx";
-        String appSecret = "yyyyyy";
-        String signString = "k1=v1&v1=k1testappId=xxxxxx&nonce=" + nonce + "&timestamp=" + timestamp + "yyyyyy";
-        String sign = DigestUtil.sha256Hex(signString);
-
-        // 准备参数
-        ApiSignature apiSignature = mock(ApiSignature.class);
-        when(apiSignature.appId()).thenReturn("appId");
-        when(apiSignature.timestamp()).thenReturn("timestamp");
-        when(apiSignature.nonce()).thenReturn("nonce");
-        when(apiSignature.sign()).thenReturn("sign");
-        when(apiSignature.timeout()).thenReturn(60);
-        when(apiSignature.timeUnit()).thenReturn(TimeUnit.SECONDS);
-        HttpServletRequest request = mock(HttpServletRequest.class);
-        when(request.getHeader(eq("appId"))).thenReturn(appId);
-        when(request.getHeader(eq("timestamp"))).thenReturn(String.valueOf(timestamp));
-        when(request.getHeader(eq("nonce"))).thenReturn(nonce);
-        when(request.getHeader(eq("sign"))).thenReturn(sign);
-        when(request.getParameterMap()).thenReturn(MapUtil.<String, String[]>builder()
-                .put("v1", new String[]{"k1"}).put("k1", new String[]{"v1"}).build());
-        when(request.getContentType()).thenReturn("application/json");
-        when(request.getReader()).thenReturn(new BufferedReader(new StringReader("test")));
-        // mock 方法
-        when(signatureRedisDAO.getAppSecret(eq(appId))).thenReturn(appSecret);
-
-        // 调用
-        boolean result = apiSignatureAspect.verifySignature(apiSignature, request);
-        // 断言结果
-        assertTrue(result);
-        // 断言调用
-        verify(signatureRedisDAO).setNonce(eq(nonce), eq(120), eq(TimeUnit.SECONDS));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-redis/pom.xml b/iailab-framework/iailab-common-redis/pom.xml
deleted file mode 100644
index 5940dae..0000000
--- a/iailab-framework/iailab-common-redis/pom.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-redis</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>Redis 封装拓展</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>org.redisson</groupId>
-            <artifactId>redisson-spring-boot-starter</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-cache</artifactId> <!-- 实现对 Caches 的自动化配置 -->
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.datatype</groupId>
-            <artifactId>jackson-datatype-jsr310</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabCacheAutoConfiguration.java b/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabCacheAutoConfiguration.java
deleted file mode 100644
index 167d147..0000000
--- a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabCacheAutoConfiguration.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.iailab.framework.redis.config;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.redis.core.TimeoutRedisCacheManager;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.cache.CacheProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Primary;
-import org.springframework.data.redis.cache.BatchStrategies;
-import org.springframework.data.redis.cache.RedisCacheConfiguration;
-import org.springframework.data.redis.cache.RedisCacheManager;
-import org.springframework.data.redis.cache.RedisCacheWriter;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.serializer.RedisSerializationContext;
-import org.springframework.util.StringUtils;
-
-import java.util.Objects;
-
-import static com.iailab.framework.redis.config.IailabRedisAutoConfiguration.buildRedisSerializer;
-
-/**
- * Cache 配置类,基于 Redis 实现
- */
-@AutoConfiguration
-@EnableConfigurationProperties({CacheProperties.class, IailabCacheProperties.class})
-@EnableCaching
-public class IailabCacheAutoConfiguration {
-
-    /**
-     * RedisCacheConfiguration Bean
-     * <p>
-     * 参考 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration 的 createConfiguration 方法
-     */
-    @Bean
-    @Primary
-    public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
-        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
-        // 设置使用 : 单冒号,而不是双 :: 冒号,避免 Redis Desktop Manager 多余空格
-        // 详细可见 https://blog.csdn.net/chuixue24/article/details/103928965 博客
-        // 再次修复单冒号,而不是双 :: 冒号问题,Issues 详情:https://gitee.com/zhijiantianya/iailab-cloud/issues/I86VY2
-        config = config.computePrefixWith(cacheName -> {
-            String keyPrefix = cacheProperties.getRedis().getKeyPrefix();
-            if (StringUtils.hasText(keyPrefix)) {
-                keyPrefix = keyPrefix.lastIndexOf(StrUtil.COLON) == -1 ? keyPrefix + StrUtil.COLON : keyPrefix;
-                return keyPrefix + cacheName + StrUtil.COLON;
-            }
-            return cacheName + StrUtil.COLON;
-        });
-        // 设置使用 JSON 序列化方式
-        config = config.serializeValuesWith(
-                RedisSerializationContext.SerializationPair.fromSerializer(buildRedisSerializer()));
-
-        // 设置 CacheProperties.Redis 的属性
-        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
-        if (redisProperties.getTimeToLive() != null) {
-            config = config.entryTtl(redisProperties.getTimeToLive());
-        }
-        if (!redisProperties.isCacheNullValues()) {
-            config = config.disableCachingNullValues();
-        }
-        if (!redisProperties.isUseKeyPrefix()) {
-            config = config.disableKeyPrefix();
-        }
-        return config;
-    }
-
-    @Bean
-    public RedisCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate,
-                                               RedisCacheConfiguration redisCacheConfiguration,
-                                               IailabCacheProperties iailabCacheProperties) {
-        // 创建 RedisCacheWriter 对象
-        RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory());
-        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory,
-                BatchStrategies.scan(iailabCacheProperties.getRedisScanBatchSize()));
-        // 创建 TenantRedisCacheManager 对象
-        return new TimeoutRedisCacheManager(cacheWriter, redisCacheConfiguration);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabCacheProperties.java b/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabCacheProperties.java
deleted file mode 100644
index 2cc155f..0000000
--- a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabCacheProperties.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.redis.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-/**
- * Cache 配置项
- *
- * @author Wanwan
- */
-@ConfigurationProperties("iailab.cache")
-@Data
-@Validated
-public class IailabCacheProperties {
-
-    /**
-     * {@link #redisScanBatchSize} 默认值
-     */
-    private static final Integer REDIS_SCAN_BATCH_SIZE_DEFAULT = 30;
-
-    /**
-     * redis scan 一次返回数量
-     */
-    private Integer redisScanBatchSize = REDIS_SCAN_BATCH_SIZE_DEFAULT;
-
-}
diff --git a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabRedisAutoConfiguration.java b/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabRedisAutoConfiguration.java
deleted file mode 100644
index e63df54..0000000
--- a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/config/IailabRedisAutoConfiguration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.iailab.framework.redis.config;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import org.redisson.spring.starter.RedissonAutoConfiguration;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.serializer.RedisSerializer;
-
-/**
- * Redis 配置类
- */
-@AutoConfiguration(before = RedissonAutoConfiguration.class) // 目的:使用自己定义的 RedisTemplate Bean
-public class IailabRedisAutoConfiguration {
-
-    /**
-     * 创建 RedisTemplate Bean,使用 JSON 序列化方式
-     */
-    @Bean
-    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
-        // 创建 RedisTemplate 对象
-        RedisTemplate<String, Object> template = new RedisTemplate<>();
-        // 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。
-        template.setConnectionFactory(factory);
-        // 使用 String 序列化方式,序列化 KEY 。
-        template.setKeySerializer(RedisSerializer.string());
-        template.setHashKeySerializer(RedisSerializer.string());
-        // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。
-        template.setValueSerializer(buildRedisSerializer());
-        template.setHashValueSerializer(buildRedisSerializer());
-        return template;
-    }
-
-    public static RedisSerializer<?> buildRedisSerializer() {
-        RedisSerializer<Object> json = RedisSerializer.json();
-        // 解决 LocalDateTime 的序列化
-        ObjectMapper objectMapper = (ObjectMapper) ReflectUtil.getFieldValue(json, "mapper");
-        objectMapper.registerModules(new JavaTimeModule());
-        return json;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/core/TimeoutRedisCacheManager.java b/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/core/TimeoutRedisCacheManager.java
deleted file mode 100644
index de86678..0000000
--- a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/core/TimeoutRedisCacheManager.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.iailab.framework.redis.core;
-
-import cn.hutool.core.util.NumberUtil;
-import cn.hutool.core.util.StrUtil;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.data.redis.cache.RedisCache;
-import org.springframework.data.redis.cache.RedisCacheConfiguration;
-import org.springframework.data.redis.cache.RedisCacheManager;
-import org.springframework.data.redis.cache.RedisCacheWriter;
-
-import java.time.Duration;
-
-/**
- * 支持自定义过期时间的 {@link RedisCacheManager} 实现类
- *
- * 在 {@link Cacheable#cacheNames()} 格式为 "key#ttl" 时,# 后面的 ttl 为过期时间。
- * 单位为最后一个字母(支持的单位有:d 天,h 小时,m 分钟,s 秒),默认单位为 s 秒
- *
- * @author iailab
- */
-public class TimeoutRedisCacheManager extends RedisCacheManager {
-
-    private static final String SPLIT = "#";
-
-    public TimeoutRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
-        super(cacheWriter, defaultCacheConfiguration);
-    }
-
-    @Override
-    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
-        if (StrUtil.isEmpty(name)) {
-            return super.createRedisCache(name, cacheConfig);
-        }
-        // 如果使用 # 分隔,大小不为 2,则说明不使用自定义过期时间
-        String[] names = StrUtil.splitToArray(name, SPLIT);
-        if (names.length != 2) {
-            return super.createRedisCache(name, cacheConfig);
-        }
-
-        // 核心:通过修改 cacheConfig 的过期时间,实现自定义过期时间
-        if (cacheConfig != null) {
-            // 移除 # 后面的 : 以及后面的内容,避免影响解析
-            String ttlStr = StrUtil.subBefore(names[1], StrUtil.COLON, false); // 获得 ttlStr 时间部分
-            names[1] = StrUtil.subAfter(names[1], ttlStr, false); // 移除掉 ttlStr 时间部分
-            // 解析时间
-            Duration duration = parseDuration(ttlStr);
-            cacheConfig = cacheConfig.entryTtl(duration);
-        }
-
-        // 创建 RedisCache 对象,需要忽略掉 ttlStr
-        return super.createRedisCache(names[0] + names[1], cacheConfig);
-    }
-
-    /**
-     * 解析过期时间 Duration
-     *
-     * @param ttlStr 过期时间字符串
-     * @return 过期时间 Duration
-     */
-    private Duration parseDuration(String ttlStr) {
-        String timeUnit = StrUtil.subSuf(ttlStr, -1);
-        switch (timeUnit) {
-            case "d":
-                return Duration.ofDays(removeDurationSuffix(ttlStr));
-            case "h":
-                return Duration.ofHours(removeDurationSuffix(ttlStr));
-            case "m":
-                return Duration.ofMinutes(removeDurationSuffix(ttlStr));
-            case "s":
-                return Duration.ofSeconds(removeDurationSuffix(ttlStr));
-            default:
-                return Duration.ofSeconds(Long.parseLong(ttlStr));
-        }
-    }
-
-    /**
-     * 移除多余的后缀,返回具体的时间
-     *
-     * @param ttlStr 过期时间字符串
-     * @return 时间
-     */
-    private Long removeDurationSuffix(String ttlStr) {
-        return NumberUtil.parseLong(StrUtil.sub(ttlStr, 0, ttlStr.length() - 1));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/package-info.java b/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/package-info.java
deleted file mode 100644
index 6ce6b3a..0000000
--- a/iailab-framework/iailab-common-redis/src/main/java/com/iailab/framework/redis/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 采用 Spring Data Redis 操作 Redis,底层使用 Redisson 作为客户端
- */
-package com.iailab.framework.redis;
diff --git a/iailab-framework/iailab-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 1b9e718..0000000
--- a/iailab-framework/iailab-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.iailab.framework.redis.config.IailabRedisAutoConfiguration
-com.iailab.framework.redis.config.IailabCacheAutoConfiguration
diff --git a/iailab-framework/iailab-common-rpc/pom.xml b/iailab-framework/iailab-common-rpc/pom.xml
deleted file mode 100644
index d27e89a..0000000
--- a/iailab-framework/iailab-common-rpc/pom.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>iailab-framework</artifactId>
-        <groupId>com.iailab</groupId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-rpc</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        OpenFeign:提供 RESTful API 的调用
-    </description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- RPC 远程调用相关 -->
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-openfeign</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>io.github.openfeign</groupId>
-            <artifactId>feign-okhttp</artifactId>
-        </dependency>
-
-        <!-- 工具相关 -->
-        <dependency>
-            <groupId>jakarta.validation</groupId>
-            <artifactId>jakarta.validation-api</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/config/package-info.java b/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/config/package-info.java
deleted file mode 100644
index 60ee765..0000000
--- a/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/config/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 占坑 TODO
- */
-package com.iailab.framework.rpc.config;
diff --git a/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/core/package-info.java b/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/core/package-info.java
deleted file mode 100644
index c89314e..0000000
--- a/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/core/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 占坑 TODO
- */
-package com.iailab.framework.rpc.core;
diff --git a/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/package-info.java b/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/package-info.java
deleted file mode 100644
index b263430..0000000
--- a/iailab-framework/iailab-common-rpc/src/main/java/com/iailab/framework/rpc/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * OpenFeign:提供 RESTful API 的调用
- *
- * @author iailab
- */
-package com.iailab.framework.rpc;
diff --git a/iailab-framework/iailab-common-security/pom.xml b/iailab-framework/iailab-common-security/pom.xml
deleted file mode 100644
index feb7855..0000000
--- a/iailab-framework/iailab-common-security/pom.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-security</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>
-        1. security:用户的认证、权限的校验,实现「谁」可以做「什么事」
-        2. operatelog:操作日志,实现「谁」在「什么时间」对「什么」做了「什么事」
-    </description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Spring 核心 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-web</artifactId>
-        </dependency>
-        <!-- spring boot 配置所需依赖 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-security</artifactId>
-        </dependency>
-
-        <!-- RPC 远程调用相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-rpc</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- 业务组件 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-module-system-api</artifactId> <!-- 需要使用它,进行 Token 的校验 -->
-            <version>${revision}</version>
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-        </dependency>
-
-        <dependency>
-            <!-- Spring Boot 通用操作日志组件,基于注解实现 -->
-            <!-- 此组件解决的问题是:「谁」在「什么时间」对「什么」做了「什么事」 -->
-            <groupId>io.github.mouzt</groupId>
-            <artifactId>bizlog-sdk</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/config/IailabOperateLogConfiguration.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/config/IailabOperateLogConfiguration.java
deleted file mode 100644
index 22b90b8..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/config/IailabOperateLogConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.operatelog.config;
-
-import com.iailab.framework.operatelog.core.service.LogRecordServiceImpl;
-import com.mzt.logapi.service.ILogRecordService;
-import com.mzt.logapi.starter.annotation.EnableLogRecord;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Primary;
-
-/**
- * 操作日志配置类
- *
- * @author HUIHUI
- */
-@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦
-@AutoConfiguration
-@Slf4j
-public class IailabOperateLogConfiguration {
-
-    @Bean
-    @Primary
-    public ILogRecordService iLogRecordServiceImpl() {
-        return new LogRecordServiceImpl();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/config/IailabOperateLogRpcAutoConfiguration.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/config/IailabOperateLogRpcAutoConfiguration.java
deleted file mode 100644
index ef72d29..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/config/IailabOperateLogRpcAutoConfiguration.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.iailab.framework.operatelog.config;
-
-import com.iailab.module.system.api.logger.OperateLogApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.cloud.openfeign.EnableFeignClients;
-
-/**
- * OperateLog 使用到 Feign 的配置项
- *
- * @author iailab
- */
-@AutoConfiguration
-@EnableFeignClients(clients = {OperateLogApi.class}) // 主要是引入相关的 API 服务
-public class IailabOperateLogRpcAutoConfiguration {
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/core/package-info.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/core/package-info.java
deleted file mode 100644
index 80abe28..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/core/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 占位,无特殊作用
- */
-package com.iailab.framework.operatelog.core;
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/core/service/LogRecordServiceImpl.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/core/service/LogRecordServiceImpl.java
deleted file mode 100644
index 0e95b34..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/core/service/LogRecordServiceImpl.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.iailab.framework.operatelog.core.service;
-
-import com.iailab.framework.common.util.monitor.TracerUtils;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.module.system.api.logger.OperateLogApi;
-import com.iailab.module.system.api.logger.dto.OperateLogCreateReqDTO;
-import com.mzt.logapi.beans.LogRecord;
-import com.mzt.logapi.service.ILogRecordService;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
-import java.util.List;
-
-/**
- * 操作日志 ILogRecordService 实现类
- *
- * 基于 {@link OperateLogApi} 实现,记录操作日志
- *
- * @author HUIHUI
- */
-@Slf4j
-public class LogRecordServiceImpl implements ILogRecordService {
-
-    @Resource
-    private OperateLogApi operateLogApi;
-
-    @Override
-    public void record(LogRecord logRecord) {
-        // 1. 补全通用字段
-        OperateLogCreateReqDTO reqDTO = new OperateLogCreateReqDTO();
-        reqDTO.setTraceId(TracerUtils.getTraceId());
-        // 补充用户信息
-        fillUserFields(reqDTO);
-        // 补全模块信息
-        fillModuleFields(reqDTO, logRecord);
-        // 补全请求信息
-        fillRequestFields(reqDTO);
-
-        // 2. 异步记录日志
-        operateLogApi.createOperateLog(reqDTO);
-    }
-
-    private static void fillUserFields(OperateLogCreateReqDTO reqDTO) {
-        // 使用 SecurityFrameworkUtils。因为要考虑,rpc、mq、job,它其实不是 web;
-        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
-        if (loginUser == null) {
-            return;
-        }
-        reqDTO.setUserId(loginUser.getId());
-        reqDTO.setUserType(loginUser.getUserType());
-    }
-
-    public static void fillModuleFields(OperateLogCreateReqDTO reqDTO, LogRecord logRecord) {
-        reqDTO.setType(logRecord.getType()); // 大模块类型,例如:CRM 客户
-        reqDTO.setSubType(logRecord.getSubType());// 操作名称,例如:转移客户
-        reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 业务编号,例如:客户编号
-        reqDTO.setAction(logRecord.getAction());// 操作内容,例如:修改编号为 1 的用户信息,将性别从男改成女,将姓名从平台改成源码。
-        reqDTO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"}
-    }
-
-    private static void fillRequestFields(OperateLogCreateReqDTO reqDTO) {
-        // 获得 Request 对象
-        HttpServletRequest request = ServletUtils.getRequest();
-        if (request == null) {
-            return;
-        }
-        // 补全请求信息
-        reqDTO.setRequestMethod(request.getMethod());
-        reqDTO.setRequestUrl(request.getRequestURI());
-        reqDTO.setUserIp(ServletUtils.getClientIP(request));
-        reqDTO.setUserAgent(ServletUtils.getUserAgent(request));
-    }
-
-    @Override
-    public List<LogRecord> queryLog(String bizNo, String type) {
-        throw new UnsupportedOperationException("使用 OperateLogApi 进行操作日志的查询");
-    }
-
-    @Override
-    public List<LogRecord> queryLogByBizNo(String bizNo, String type, String subType) {
-        throw new UnsupportedOperationException("使用 OperateLogApi 进行操作日志的查询");
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/package-info.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/package-info.java
deleted file mode 100644
index 9df12ab..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/operatelog/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * 基于 mzt-log 框架
- * 实现操作日志功能
- *
- * @author HUIHUI
- */
-package com.iailab.framework.operatelog;
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/AuthorizeRequestsCustomizer.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/AuthorizeRequestsCustomizer.java
deleted file mode 100644
index 063c85e..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/AuthorizeRequestsCustomizer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.security.config;
-
-import com.iailab.framework.web.config.WebProperties;
-import org.springframework.core.Ordered;
-import org.springframework.security.config.Customizer;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
-import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
-
-import javax.annotation.Resource;
-
-/**
- * 自定义的 URL 的安全配置
- * 目的:每个 Maven Module 可以自定义规则!
- *
- * @author iailab
- */
-public abstract class AuthorizeRequestsCustomizer
-        implements Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry>, Ordered {
-
-    @Resource
-    private WebProperties webProperties;
-
-    protected String buildAdminApi(String url) {
-        return webProperties.getAdminApi().getPrefix() + url;
-    }
-
-    protected String buildAppApi(String url) {
-        return webProperties.getAppApi().getPrefix() + url;
-    }
-
-    @Override
-    public int getOrder() {
-        return 0;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityAutoConfiguration.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityAutoConfiguration.java
deleted file mode 100644
index 4ab66ee..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityAutoConfiguration.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.iailab.framework.security.config;
-
-import cn.hutool.extra.spring.SpringUtil;
-import com.iailab.framework.security.core.aop.PreAuthenticatedAspect;
-import com.iailab.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
-import com.iailab.framework.security.core.filter.TokenAuthenticationFilter;
-import com.iailab.framework.security.core.handler.AccessDeniedHandlerImpl;
-import com.iailab.framework.security.core.handler.AuthenticationEntryPointImpl;
-import com.iailab.framework.security.core.service.SecurityFrameworkService;
-import com.iailab.framework.security.core.service.SecurityFrameworkServiceImpl;
-import com.iailab.framework.web.core.handler.GlobalExceptionHandler;
-import com.iailab.module.system.api.oauth2.OAuth2TokenApi;
-import com.iailab.module.system.api.permission.PermissionApi;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.AutoConfigureOrder;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.access.AccessDeniedHandler;
-
-import javax.annotation.Resource;
-
-/**
- * Spring Security 自动配置类,主要用于相关组件的配置
- *
- * 注意,不能和 {@link IailabWebSecurityConfigurerAdapter} 用一个,原因是会导致初始化报错。
- * 参见 https://stackoverflow.com/questions/53847050/spring-boot-delegatebuilder-cannot-be-null-on-autowiring-authenticationmanager 文档。
- *
- * @author iailab
- */
-@AutoConfiguration
-@AutoConfigureOrder(-1) // 目的:先于 Spring Security 自动配置,避免一键改包后,org.* 基础包无法生效
-@EnableConfigurationProperties(SecurityProperties.class)
-public class IailabSecurityAutoConfiguration {
-
-    @Resource
-    private SecurityProperties securityProperties;
-
-    /**
-     * 处理用户未登录拦截的切面的 Bean
-     */
-    @Bean
-    public PreAuthenticatedAspect preAuthenticatedAspect() {
-        return new PreAuthenticatedAspect();
-    }
-
-    /**
-     * 认证失败处理类 Bean
-     */
-    @Bean
-    public AuthenticationEntryPoint authenticationEntryPoint() {
-        return new AuthenticationEntryPointImpl();
-    }
-
-    /**
-     * 权限不够处理器 Bean
-     */
-    @Bean
-    public AccessDeniedHandler accessDeniedHandler() {
-        return new AccessDeniedHandlerImpl();
-    }
-
-    /**
-     * Spring Security 加密器
-     * 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器
-     *
-     * @see <a href="http://stackabuse.com/password-encoding-with-spring-security/">Password Encoding with Spring Security</a>
-     */
-    @Bean
-    public PasswordEncoder passwordEncoder() {
-        return new BCryptPasswordEncoder(securityProperties.getPasswordEncoderLength());
-    }
-
-    /**
-     * Token 认证过滤器 Bean
-     */
-    @Bean
-    public TokenAuthenticationFilter authenticationTokenFilter(GlobalExceptionHandler globalExceptionHandler,
-                                                               OAuth2TokenApi oauth2TokenApi) {
-        try {
-            OAuth2TokenApi oAuth2TokenApi = SpringUtil.getBean("aAuth2TokenApiImpl", OAuth2TokenApi.class);
-            if (oAuth2TokenApi != null) {
-                oauth2TokenApi = oAuth2TokenApi;
-            }
-        } catch (Exception ignored) {}
-        return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler, oauth2TokenApi);
-    }
-
-    @Bean("ss") // 使用 Spring Security 的缩写,方便使用
-    public SecurityFrameworkService securityFrameworkService(PermissionApi permissionApi) {
-        try {
-            PermissionApi permissionApiImpl = SpringUtil.getBean("permissionApiImpl", PermissionApi.class);
-            if (permissionApiImpl != null) {
-                permissionApi = permissionApiImpl;
-            }
-        } catch (Exception ignored) {}
-        return new SecurityFrameworkServiceImpl(permissionApi);
-    }
-
-    /**
-     * 声明调用 {@link SecurityContextHolder#setStrategyName(String)} 方法,
-     * 设置使用 {@link TransmittableThreadLocalSecurityContextHolderStrategy} 作为 Security 的上下文策略
-     */
-    @Bean
-    public MethodInvokingFactoryBean securityContextHolderMethodInvokingFactoryBean() {
-        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
-        methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
-        methodInvokingFactoryBean.setTargetMethod("setStrategyName");
-        methodInvokingFactoryBean.setArguments(TransmittableThreadLocalSecurityContextHolderStrategy.class.getName());
-        return methodInvokingFactoryBean;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityRpcAutoConfiguration.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityRpcAutoConfiguration.java
deleted file mode 100644
index c707419..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabSecurityRpcAutoConfiguration.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.security.config;
-
-import com.iailab.framework.security.core.rpc.LoginUserRequestInterceptor;
-import com.iailab.module.system.api.oauth2.OAuth2TokenApi;
-import com.iailab.module.system.api.permission.PermissionApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.cloud.openfeign.EnableFeignClients;
-import org.springframework.context.annotation.Bean;
-
-/**
- * Security 使用到 Feign 的配置项
- *
- * @author iailab
- */
-@AutoConfiguration
-@EnableFeignClients(clients = {OAuth2TokenApi.class, // 主要是引入相关的 API 服务
-        PermissionApi.class})
-public class IailabSecurityRpcAutoConfiguration {
-
-    @Bean
-    public LoginUserRequestInterceptor loginUserRequestInterceptor() {
-        return new LoginUserRequestInterceptor();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabWebSecurityConfigurerAdapter.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabWebSecurityConfigurerAdapter.java
deleted file mode 100644
index 4813ecf..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/IailabWebSecurityConfigurerAdapter.java
+++ /dev/null
@@ -1,217 +0,0 @@
-package com.iailab.framework.security.config;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.security.core.filter.TokenAuthenticationFilter;
-import com.iailab.framework.web.config.WebProperties;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.AutoConfigureOrder;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.http.HttpMethod;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.config.Customizer;
-import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
-import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
-import org.springframework.security.config.http.SessionCreationPolicy;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.access.AccessDeniedHandler;
-import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
-import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-import org.springframework.web.util.pattern.PathPattern;
-
-import javax.annotation.Resource;
-import javax.annotation.security.PermitAll;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
-
-/**
- * 自定义的 Spring Security 配置适配器实现
- *
- * @author iailab
- */
-@AutoConfiguration
-@AutoConfigureOrder(-1) // 目的:先于 Spring Security 自动配置,避免一键改包后,org.* 基础包无法生效
-@EnableMethodSecurity(securedEnabled = true)
-public class IailabWebSecurityConfigurerAdapter {
-
-    @Resource
-    private WebProperties webProperties;
-    @Resource
-    private SecurityProperties securityProperties;
-
-    /**
-     * 认证失败处理类 Bean
-     */
-    @Resource
-    private AuthenticationEntryPoint authenticationEntryPoint;
-    /**
-     * 权限不够处理器 Bean
-     */
-    @Resource
-    private AccessDeniedHandler accessDeniedHandler;
-    /**
-     * Token 认证过滤器 Bean
-     */
-    @Resource
-    private TokenAuthenticationFilter authenticationTokenFilter;
-
-    /**
-     * 自定义的权限映射 Bean 们
-     *
-     * @see #filterChain(HttpSecurity)
-     */
-    @Resource
-    private List<AuthorizeRequestsCustomizer> authorizeRequestsCustomizers;
-
-    @Resource
-    private ApplicationContext applicationContext;
-
-    /**
-     * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入
-     * 通过覆写父类的该方法,添加 @Bean 注解,解决该问题
-     */
-    @Bean
-    public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authenticationConfiguration) throws Exception {
-        return authenticationConfiguration.getAuthenticationManager();
-    }
-
-    /**
-     * 配置 URL 的安全配置
-     *
-     * anyRequest          |   匹配所有请求路径
-     * access              |   SpringEl表达式结果为true时可以访问
-     * anonymous           |   匿名可以访问
-     * denyAll             |   用户不能访问
-     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
-     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
-     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
-     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
-     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
-     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
-     * permitAll           |   用户可以任意访问
-     * rememberMe          |   允许通过remember-me登录的用户访问
-     * authenticated       |   用户登录后可访问
-     */
-    @Bean
-    protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
-        // 登出
-        httpSecurity
-                // 开启跨域
-                .cors(Customizer.withDefaults())
-                // CSRF 禁用,因为不使用 Session
-                .csrf(AbstractHttpConfigurer::disable)
-                // 基于 token 机制,所以不需要 Session
-                .sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
-                .headers(c -> c.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
-                // 一堆自定义的 Spring Security 处理器
-                .exceptionHandling(c -> c.authenticationEntryPoint(authenticationEntryPoint)
-                        .accessDeniedHandler(accessDeniedHandler));
-        // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高
-
-        // 获得 @PermitAll 带来的 URL 列表,免登录
-        Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations();
-        // 设置每个请求的权限
-        httpSecurity
-                // ①:全局共享规则
-                .authorizeHttpRequests(c -> c
-                        // 1.1 静态资源,可匿名访问
-                        .requestMatchers(HttpMethod.GET, "/*.html", "/*.html", "/*.css", "/*.js").permitAll()
-                        // 1.2 设置 @PermitAll 无需认证
-                        .requestMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
-                        .requestMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
-                        .requestMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
-                        .requestMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
-                        .requestMatchers(HttpMethod.HEAD, permitAllUrls.get(HttpMethod.HEAD).toArray(new String[0])).permitAll()
-                        .requestMatchers(HttpMethod.PATCH, permitAllUrls.get(HttpMethod.PATCH).toArray(new String[0])).permitAll()
-                        // 1.3 基于 yudao.security.permit-all-urls 无需认证
-                        .requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
-                )
-                // ②:每个项目的自定义规则
-                .authorizeHttpRequests(c -> authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(c)))
-                // ③:兜底规则,必须认证
-                .authorizeHttpRequests(c -> c.anyRequest().authenticated());
-
-        // 添加 Token Filter
-        httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
-        return httpSecurity.build();
-    }
-
-    private String buildAppApi(String url) {
-        return webProperties.getAppApi().getPrefix() + url;
-    }
-
-    private Multimap<HttpMethod, String> getPermitAllUrlsFromAnnotations() {
-        Multimap<HttpMethod, String> result = HashMultimap.create();
-        // 获得接口对应的 HandlerMethod 集合
-        RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
-                applicationContext.getBean("requestMappingHandlerMapping");
-        Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
-        // 获得有 @PermitAll 注解的接口
-        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
-            HandlerMethod handlerMethod = entry.getValue();
-            if (!handlerMethod.hasMethodAnnotation(PermitAll.class)) {
-                continue;
-            }
-            Set<String> urls = new HashSet<>();
-            if (entry.getKey().getPatternsCondition() != null) {
-                urls.addAll(entry.getKey().getPatternsCondition().getPatterns());
-            }
-            if (entry.getKey().getPathPatternsCondition() != null) {
-                urls.addAll(convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
-            }
-            if (urls.isEmpty()) {
-                continue;
-            }
-
-            // 特殊:使用 @RequestMapping 注解,并且未写 method 属性,此时认为都需要免登录
-            Set<RequestMethod> methods = entry.getKey().getMethodsCondition().getMethods();
-            if (CollUtil.isEmpty(methods)) {
-                result.putAll(HttpMethod.GET, urls);
-                result.putAll(HttpMethod.POST, urls);
-                result.putAll(HttpMethod.PUT, urls);
-                result.putAll(HttpMethod.DELETE, urls);
-                result.putAll(HttpMethod.HEAD, urls);
-                result.putAll(HttpMethod.PATCH, urls);
-                continue;
-            }
-            // 根据请求方法,添加到 result 结果
-            entry.getKey().getMethodsCondition().getMethods().forEach(requestMethod -> {
-                switch (requestMethod) {
-                    case GET:
-                        result.putAll(HttpMethod.GET, urls);
-                        break;
-                    case POST:
-                        result.putAll(HttpMethod.POST, urls);
-                        break;
-                    case PUT:
-                        result.putAll(HttpMethod.PUT, urls);
-                        break;
-                    case DELETE:
-                        result.putAll(HttpMethod.DELETE, urls);
-                        break;
-                    case HEAD:
-                        result.putAll(HttpMethod.HEAD, urls);
-                        break;
-                    case PATCH:
-                        result.putAll(HttpMethod.PATCH, urls);
-                        break;
-                }
-            });
-        }
-        return result;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/SecurityProperties.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/SecurityProperties.java
deleted file mode 100644
index 57a6b47..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/config/SecurityProperties.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.iailab.framework.security.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-import java.util.Collections;
-import java.util.List;
-
-@ConfigurationProperties(prefix = "iailab.security")
-@Validated
-@Data
-public class SecurityProperties {
-
-    /**
-     * HTTP 请求时,访问令牌的请求 Header
-     */
-    @NotEmpty(message = "Token Header 不能为空")
-    private String tokenHeader = "Authorization";
-    /**
-     * HTTP 请求时,访问令牌的请求参数
-     *
-     * 初始目的:解决 WebSocket 无法通过 header 传参,只能通过 token 参数拼接
-     */
-    @NotEmpty(message = "Token Parameter 不能为空")
-    private String tokenParameter = "token";
-
-    /**
-     * mock 模式的开关
-     */
-    @NotNull(message = "mock 模式的开关不能为空")
-    private Boolean mockEnable = false;
-    /**
-     * mock 模式的密钥
-     * 一定要配置密钥,保证安全性
-     */
-    @NotEmpty(message = "mock 模式的密钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。
-    private String mockSecret = "test";
-
-    /**
-     * 免登录的 URL 列表
-     */
-    private List<String> permitAllUrls = Collections.emptyList();
-
-    /**
-     * PasswordEncoder 加密复杂度,越高开销越大
-     */
-    private Integer passwordEncoderLength = 4;
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/LoginUser.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/LoginUser.java
deleted file mode 100644
index 989ef9a..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/LoginUser.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.iailab.framework.security.core;
-
-import cn.hutool.core.map.MapUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 登录用户信息
- *
- * @author iailab
- */
-@Data
-public class LoginUser {
-
-    public static final String INFO_KEY_NICKNAME = "nickname";
-    public static final String INFO_KEY_DEPT_ID = "deptId";
-
-    /**
-     * 用户编号
-     */
-    private Long id;
-    /**
-     * 用户类型
-     *
-     * 关联 {@link UserTypeEnum}
-     */
-    private Integer userType;
-    /**
-     * 额外的用户信息
-     */
-    private Map<String, String> info;
-    /**
-     * 租户编号
-     */
-    private Long tenantId;
-    /**
-     * 授权范围
-     */
-    private List<String> scopes;
-    /**
-     * 过期时间
-     */
-    private LocalDateTime expiresTime;
-    /**
-     * 访问令牌
-     */
-    private String accessToken;
-
-    // ========== 上下文 ==========
-    /**
-     * 上下文字段,不进行持久化
-     *
-     * 1. 用于基于 LoginUser 维度的临时缓存
-     */
-    @JsonIgnore
-    private Map<String, Object> context;
-
-    public void setContext(String key, Object value) {
-        if (context == null) {
-            context = new HashMap<>();
-        }
-        context.put(key, value);
-    }
-
-    public <T> T getContext(String key, Class<T> type) {
-        return MapUtil.get(context, key, type);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/annotations/PreAuthenticated.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/annotations/PreAuthenticated.java
deleted file mode 100644
index f2f6c6c..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/annotations/PreAuthenticated.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.iailab.framework.security.core.annotations;
-
-import java.lang.annotation.*;
-
-/**
- * 声明用户需要登录
- *
- * 为什么不使用 {@link org.springframework.security.access.prepost.PreAuthorize} 注解,原因是不通过时,抛出的是认证不通过,而不是未登录
- *
- * @author iailab
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-@Documented
-public @interface PreAuthenticated {
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/aop/PreAuthenticatedAspect.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/aop/PreAuthenticatedAspect.java
deleted file mode 100644
index 806207a..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/aop/PreAuthenticatedAspect.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.security.core.aop;
-
-import com.iailab.framework.security.core.annotations.PreAuthenticated;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-
-@Aspect
-@Slf4j
-public class PreAuthenticatedAspect {
-
-    @Around("@annotation(preAuthenticated)")
-    public Object around(ProceedingJoinPoint joinPoint, PreAuthenticated preAuthenticated) throws Throwable {
-        if (SecurityFrameworkUtils.getLoginUser() == null) {
-            throw exception(UNAUTHORIZED);
-        }
-        return joinPoint.proceed();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java
deleted file mode 100644
index 5eefcfe..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.iailab.framework.security.core.context;
-
-import com.alibaba.ttl.TransmittableThreadLocal;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolderStrategy;
-import org.springframework.security.core.context.SecurityContextImpl;
-import org.springframework.util.Assert;
-
-/**
- * 基于 TransmittableThreadLocal 实现的 Security Context 持有者策略
- * 目的是,避免 @Async 等异步执行时,原生 ThreadLocal 的丢失问题
- *
- * @author iailab
- */
-public class TransmittableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
-
-    /**
-     * 使用 TransmittableThreadLocal 作为上下文
-     */
-    private static final ThreadLocal<SecurityContext> CONTEXT_HOLDER = new TransmittableThreadLocal<>();
-
-    @Override
-    public void clearContext() {
-        CONTEXT_HOLDER.remove();
-    }
-
-    @Override
-    public SecurityContext getContext() {
-        SecurityContext ctx = CONTEXT_HOLDER.get();
-        if (ctx == null) {
-            ctx = createEmptyContext();
-            CONTEXT_HOLDER.set(ctx);
-        }
-        return ctx;
-    }
-
-    @Override
-    public void setContext(SecurityContext context) {
-        Assert.notNull(context, "Only non-null SecurityContext instances are permitted");
-        CONTEXT_HOLDER.set(context);
-    }
-
-    @Override
-    public SecurityContext createEmptyContext() {
-        return new SecurityContextImpl();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/filter/TokenAuthenticationFilter.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/filter/TokenAuthenticationFilter.java
deleted file mode 100644
index 161e12f..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/filter/TokenAuthenticationFilter.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package com.iailab.framework.security.core.filter;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.security.config.SecurityProperties;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.framework.web.core.handler.GlobalExceptionHandler;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import com.iailab.module.system.api.oauth2.OAuth2TokenApi;
-import com.iailab.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
-import lombok.RequiredArgsConstructor;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-
-/**
- * Token 过滤器,验证 token 的有效性
- * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-@Slf4j
-public class TokenAuthenticationFilter extends OncePerRequestFilter {
-
-    private final SecurityProperties securityProperties;
-
-    private final GlobalExceptionHandler globalExceptionHandler;
-
-    private final OAuth2TokenApi oauth2TokenApi;
-
-    @Override
-    @SuppressWarnings("NullableProblems")
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        // 情况一,基于 header[login-user] 获得用户,例如说来自 Gateway 或者其它服务透传
-        LoginUser loginUser = buildLoginUserByHeader(request);
-
-        // 情况二,基于 Token 获得用户
-        // 注意,这里主要满足直接使用 Nginx 直接转发到 Spring Cloud 服务的场景。
-        if (loginUser == null) {
-            String token = SecurityFrameworkUtils.obtainAuthorization(request,
-                    securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
-            if (StrUtil.isNotEmpty(token)) {
-                Integer userType = WebFrameworkUtils.getLoginUserType(request);
-                try {
-                    // 1.1 基于 token 构建登录用户
-                    loginUser = buildLoginUserByToken(token, userType);
-                    // 1.2 模拟 Login 功能,方便日常开发调试
-                    if (loginUser == null) {
-                        loginUser = mockLoginUser(request, token, userType);
-                    }
-                } catch (Throwable ex) {
-                    CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
-                    ServletUtils.writeJSON(response, result);
-                    return;
-                }
-            }
-        }
-
-        // 设置当前用户
-        if (loginUser != null) {
-            SecurityFrameworkUtils.setLoginUser(loginUser, request);
-        }
-        // 继续过滤链
-        chain.doFilter(request, response);
-    }
-
-    private LoginUser buildLoginUserByToken(String token, Integer userType) {
-        try {
-            // 校验访问令牌
-            OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token).getCheckedData();
-            if (accessToken == null) {
-                return null;
-            }
-            // 用户类型不匹配,无权限
-            // 注意:只有 /admin-api/* 和 /app-api/* 有 userType,才需要比对用户类型
-            // 类似 WebSocket 的 /ws/* 连接地址,是不需要比对用户类型的
-            if (userType != null
-                    && ObjectUtil.notEqual(accessToken.getUserType(), userType)) {
-                throw new AccessDeniedException("错误的用户类型");
-            }
-            // 构建登录用户
-            return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
-                    .setInfo(accessToken.getUserInfo()) // 额外的用户信息
-                    .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes())
-                    .setExpiresTime(accessToken.getExpiresTime());
-        } catch (ServiceException serviceException) {
-            // 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可
-            return null;
-        }
-    }
-
-    /**
-     * 模拟登录用户,方便日常开发调试
-     *
-     * 注意,在线上环境下,一定要关闭该功能!!!
-     *
-     * @param request 请求
-     * @param token 模拟的 token,格式为 {@link SecurityProperties#getMockSecret()} + 用户编号
-     * @param userType 用户类型
-     * @return 模拟的 LoginUser
-     */
-    private LoginUser mockLoginUser(HttpServletRequest request, String token, Integer userType) {
-        if (!securityProperties.getMockEnable()) {
-            return null;
-        }
-        // 必须以 mockSecret 开头
-        if (!token.startsWith(securityProperties.getMockSecret())) {
-            return null;
-        }
-        // 构建模拟用户
-        Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length()));
-        return new LoginUser().setId(userId).setUserType(userType)
-                .setTenantId(WebFrameworkUtils.getTenantId(request));
-    }
-
-    @SneakyThrows
-    private LoginUser buildLoginUserByHeader(HttpServletRequest request) {
-        String loginUserStr = request.getHeader(SecurityFrameworkUtils.LOGIN_USER_HEADER);
-        if (StrUtil.isEmpty(loginUserStr)) {
-            return null;
-        }
-        try {
-            loginUserStr = URLDecoder.decode(loginUserStr, StandardCharsets.UTF_8.name()); // 解码,解决中文乱码问题
-            return JsonUtils.parseObject(loginUserStr, LoginUser.class);
-        } catch (Exception ex) {
-            log.error("[buildLoginUserByHeader][解析 LoginUser({}) 发生异常]", loginUserStr, ex);  ;
-            throw ex;
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/handler/AccessDeniedHandlerImpl.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/handler/AccessDeniedHandlerImpl.java
deleted file mode 100644
index 0573f50..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/handler/AccessDeniedHandlerImpl.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.iailab.framework.security.core.handler;
-
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.web.access.AccessDeniedHandler;
-import org.springframework.security.web.access.ExceptionTranslationFilter;
-import org.springframework.stereotype.Component;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
-
-/**
- * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。
- *
- * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类
- *
- * @author iailab
- */
-@Slf4j
-@SuppressWarnings("JavadocReference")
-public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
-
-    @Override
-    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e)
-            throws IOException, ServletException {
-        // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏
-        log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(),
-                SecurityFrameworkUtils.getLoginUserId(), e);
-        // 返回 403
-        ServletUtils.writeJSON(response, CommonResult.error(FORBIDDEN));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/handler/AuthenticationEntryPointImpl.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/handler/AuthenticationEntryPointImpl.java
deleted file mode 100644
index dc769b7..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/handler/AuthenticationEntryPointImpl.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.security.core.handler;
-
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.security.web.access.ExceptionTranslationFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
-
-/**
- * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页
- *
- * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类
- *
- * @author ruoyi
- */
-@Slf4j
-@SuppressWarnings("JavadocReference") // 忽略文档引用报错
-public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
-
-    @Override
-    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {
-        log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e);
-        // 返回 401
-        ServletUtils.writeJSON(response, CommonResult.error(UNAUTHORIZED));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/rpc/LoginUserRequestInterceptor.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/rpc/LoginUserRequestInterceptor.java
deleted file mode 100644
index 4f89c15..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/rpc/LoginUserRequestInterceptor.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.framework.security.core.rpc;
-
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import feign.RequestInterceptor;
-import feign.RequestTemplate;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-
-/**
- * LoginUser 的 RequestInterceptor 实现类:Feign 请求时,将 {@link LoginUser} 设置到 header 中,继续透传给被调用的服务
- *
- * @author iailab
- */
-@Slf4j
-public class LoginUserRequestInterceptor implements RequestInterceptor {
-
-    @Override
-    @SneakyThrows
-    public void apply(RequestTemplate requestTemplate) {
-        LoginUser user = SecurityFrameworkUtils.getLoginUser();
-        if (user == null) {
-            return;
-        }
-        try {
-            String userStr = JsonUtils.toJsonString(user);
-            userStr = URLEncoder.encode(userStr, StandardCharsets.UTF_8.name()); // 编码,避免中文乱码
-            requestTemplate.header(SecurityFrameworkUtils.LOGIN_USER_HEADER, userStr);
-        } catch (Exception ex) {
-            log.error("[apply][序列化 LoginUser({}) 发生异常]", user, ex);
-            throw ex;
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/service/SecurityFrameworkService.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/service/SecurityFrameworkService.java
deleted file mode 100644
index a32f9f5..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/service/SecurityFrameworkService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.iailab.framework.security.core.service;
-
-/**
- * Security 框架 Service 接口,定义权限相关的校验操作
- *
- * @author iailab
- */
-public interface SecurityFrameworkService {
-
-    /**
-     * 判断是否有权限
-     *
-     * @param permission 权限
-     * @return 是否
-     */
-    boolean hasPermission(String permission);
-
-    /**
-     * 判断是否有权限,任一一个即可
-     *
-     * @param permissions 权限
-     * @return 是否
-     */
-    boolean hasAnyPermissions(String... permissions);
-
-    /**
-     * 判断是否有角色
-     *
-     * 注意,角色使用的是 SysRoleDO 的 code 标识
-     *
-     * @param role 角色
-     * @return 是否
-     */
-    boolean hasRole(String role);
-
-    /**
-     * 判断是否有角色,任一一个即可
-     *
-     * @param roles 角色数组
-     * @return 是否
-     */
-    boolean hasAnyRoles(String... roles);
-
-    /**
-     * 判断是否有授权
-     *
-     * @param scope 授权
-     * @return 是否
-     */
-    boolean hasScope(String scope);
-
-    /**
-     * 判断是否有授权范围,任一一个即可
-     *
-     * @param scope 授权范围数组
-     * @return 是否
-     */
-    boolean hasAnyScopes(String... scope);
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/service/SecurityFrameworkServiceImpl.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/service/SecurityFrameworkServiceImpl.java
deleted file mode 100644
index c4e4ec1..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/service/SecurityFrameworkServiceImpl.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.iailab.framework.security.core.service;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.module.system.api.permission.PermissionApi;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import lombok.AllArgsConstructor;
-import lombok.SneakyThrows;
-
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.List;
-
-import static com.iailab.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
-import static com.iailab.framework.common.util.cache.CacheUtils.buildCache;
-import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-
-/**
- * 默认的 {@link SecurityFrameworkService} 实现类
- *
- * @author iailab
- */
-@AllArgsConstructor
-public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
-
-    private final PermissionApi permissionApi;
-
-    /**
-     * 针对 {@link #hasAnyRoles(String...)} 的缓存
-     */
-    private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyRolesCache = buildCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<KeyValue<Long, List<String>>, Boolean>() {
-
-                @Override
-                public Boolean load(KeyValue<Long, List<String>> key) {
-                    return permissionApi.hasAnyRoles(key.getKey(), key.getValue().toArray(new String[0])).getCheckedData();
-                }
-
-            });
-
-    /**
-     * 针对 {@link #hasAnyPermissions(String...)} 的缓存
-     */
-    private final LoadingCache<KeyValue<Long, List<String>>, Boolean> hasAnyPermissionsCache = buildCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<KeyValue<Long, List<String>>, Boolean>() {
-
-                @Override
-                public Boolean load(KeyValue<Long, List<String>> key) {
-                    return permissionApi.hasAnyPermissions(key.getKey(), key.getValue().toArray(new String[0])).getCheckedData();
-                }
-
-            });
-
-    @Override
-    public boolean hasPermission(String permission) {
-        return hasAnyPermissions(permission);
-    }
-
-    @Override
-    @SneakyThrows
-    public boolean hasAnyPermissions(String... permissions) {
-        Long userId = getLoginUserId();
-        if (userId == null) {
-            return false;
-        }
-        return hasAnyPermissionsCache.get(new KeyValue<>(userId, Arrays.asList(permissions)));
-    }
-
-    @Override
-    public boolean hasRole(String role) {
-        return hasAnyRoles(role);
-    }
-
-    @Override
-    @SneakyThrows
-    public boolean hasAnyRoles(String... roles) {
-        Long userId = getLoginUserId();
-        if (userId == null) {
-            return false;
-        }
-        return hasAnyRolesCache.get(new KeyValue<>(userId, Arrays.asList(roles)));
-    }
-
-    @Override
-    public boolean hasScope(String scope) {
-        return hasAnyScopes(scope);
-    }
-
-    @Override
-    public boolean hasAnyScopes(String... scope) {
-        LoginUser user = SecurityFrameworkUtils.getLoginUser();
-        if (user == null) {
-            return false;
-        }
-        return CollUtil.containsAny(user.getScopes(), Arrays.asList(scope));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/util/SecurityFrameworkUtils.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/util/SecurityFrameworkUtils.java
deleted file mode 100644
index c940895..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/core/util/SecurityFrameworkUtils.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package com.iailab.framework.security.core.util;
-
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.springframework.lang.Nullable;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
-import org.springframework.util.StringUtils;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Collections;
-
-/**
- * 安全服务工具类
- *
- * @author iailab
- */
-public class SecurityFrameworkUtils {
-
-    /**
-     * HEADER 认证头 value 的前缀
-     */
-    public static final String AUTHORIZATION_BEARER = "Bearer";
-
-    public static final String LOGIN_USER_HEADER = "login-user";
-
-    private SecurityFrameworkUtils() {}
-
-    /**
-     * 从请求中,获得认证 Token
-     *
-     * @param request 请求
-     * @param headerName 认证 Token 对应的 Header 名字
-     * @param parameterName 认证 Token 对应的 Parameter 名字
-     * @return 认证 Token
-     */
-    public static String obtainAuthorization(HttpServletRequest request,
-                                             String headerName, String parameterName) {
-        // 1. 获得 Token。优先级:Header > Parameter
-        String token = request.getHeader(headerName);
-        if (StrUtil.isEmpty(token)) {
-            token = request.getParameter(parameterName);
-        }
-        if (!StringUtils.hasText(token)) {
-            return null;
-        }
-        // 2. 去除 Token 中带的 Bearer
-        int index = token.indexOf(AUTHORIZATION_BEARER + " ");
-        return index >= 0 ? token.substring(index + 7).trim() : token;
-    }
-
-    /**
-     * 获得当前认证信息
-     *
-     * @return 认证信息
-     */
-    public static Authentication getAuthentication() {
-        SecurityContext context = SecurityContextHolder.getContext();
-        if (context == null) {
-            return null;
-        }
-        return context.getAuthentication();
-    }
-
-    /**
-     * 获取当前用户
-     *
-     * @return 当前用户
-     */
-    @Nullable
-    public static LoginUser getLoginUser() {
-        Authentication authentication = getAuthentication();
-        if (authentication == null) {
-            return null;
-        }
-        return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null;
-    }
-
-    /**
-     * 获得当前用户的编号,从上下文中
-     *
-     * @return 用户编号
-     */
-    @Nullable
-    public static Long getLoginUserId() {
-        LoginUser loginUser = getLoginUser();
-        return loginUser != null ? loginUser.getId() : null;
-    }
-
-    /**
-     * 获得当前用户的昵称,从上下文中
-     *
-     * @return 昵称
-     */
-    @Nullable
-    public static String getLoginUserNickname() {
-        LoginUser loginUser = getLoginUser();
-        return loginUser != null ? MapUtil.getStr(loginUser.getInfo(), LoginUser.INFO_KEY_NICKNAME) : null;
-    }
-
-    /**
-     * 获得当前用户的部门编号,从上下文中
-     *
-     * @return 部门编号
-     */
-    @Nullable
-    public static Long getLoginUserDeptId() {
-        LoginUser loginUser = getLoginUser();
-        return loginUser != null ? MapUtil.getLong(loginUser.getInfo(), LoginUser.INFO_KEY_DEPT_ID) : null;
-    }
-
-    /**
-     * 设置当前用户
-     *
-     * @param loginUser 登录用户
-     * @param request 请求
-     */
-    public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
-        // 创建 Authentication,并设置到上下文
-        Authentication authentication = buildAuthentication(loginUser, request);
-        SecurityContextHolder.getContext().setAuthentication(authentication);
-
-        // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
-        // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
-        WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
-        WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
-    }
-
-    private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
-        // 创建 UsernamePasswordAuthenticationToken 对象
-        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
-                loginUser, null, Collections.emptyList());
-        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
-        return authenticationToken;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/package-info.java b/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/package-info.java
deleted file mode 100644
index aac86f2..0000000
--- a/iailab-framework/iailab-common-security/src/main/java/com/iailab/framework/security/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * 基于 Spring Security 框架
- * 实现安全认证功能
- *
- * @author iailab
- */
-package com.iailab.framework.security;
diff --git a/iailab-framework/iailab-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 7af8b2d..0000000
--- a/iailab-framework/iailab-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,5 +0,0 @@
-com.iailab.framework.security.config.IailabSecurityRpcAutoConfiguration
-com.iailab.framework.security.config.IailabSecurityAutoConfiguration
-com.iailab.framework.security.config.IailabWebSecurityConfigurerAdapter
-com.iailab.framework.operatelog.config.IailabOperateLogConfiguration
-com.iailab.framework.operatelog.config.IailabOperateLogRpcAutoConfiguration
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-security/src/main/resources/assembly.xml b/iailab-framework/iailab-common-security/src/main/resources/assembly.xml
deleted file mode 100644
index 22ad348..0000000
--- a/iailab-framework/iailab-common-security/src/main/resources/assembly.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
-          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
-<!--    <id>jar-with-dependencies</id>-->
-    <formats>
-        <format>jar</format>
-    </formats>
-    <includeBaseDirectory>true</includeBaseDirectory>
-
-    <!--依赖jar包以及项目打包文件存储文件-->
-    <dependencySets>
-        <dependencySet>
-            <!--存储在projectName-assembly-version/lib下-->
-            <outputDirectory>lib</outputDirectory>
-        </dependencySet>
-    </dependencySets>
-
-    <files>
-        <file>
-            <fileMode>775</fileMode>
-            <source>target/${project.build.finalName}.jar</source>
-            <destName>demo-maven-assembly.jar</destName>
-            <outputDirectory>./target</outputDirectory>
-        </file>
-    </files>
-
-    <fileSets>
-        <fileSet>
-            <directory>src/main/resources</directory>
-            <outputDirectory>./conf</outputDirectory>
-            <includes>
-                <include>*.yml</include>
-                <include>*.properties</include>
-            </includes>
-        </fileSet>
-        <fileSet>
-            <fileMode>775</fileMode>
-            <directory>deploy/bin</directory>
-            <outputDirectory>./bin</outputDirectory>
-        </fileSet>
-        <fileSet>
-            <directory>${basedir}</directory>
-            <includes>
-                <include>*.md</include>
-            </includes>
-        </fileSet>
-
-    </fileSets>
-
-</assembly>
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-test/pom.xml b/iailab-framework/iailab-common-test/pom.xml
deleted file mode 100644
index 98e1a74..0000000
--- a/iailab-framework/iailab-common-test/pom.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-test</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>测试组件,用于单元测试、集成测试</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- DB 相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-mybatis</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-redis</artifactId>
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.h2database</groupId> <!-- 单元测试,我们采用 H2 作为数据库 -->
-            <artifactId>h2</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.fppt</groupId> <!-- 单元测试,我们采用内嵌的 Redis 数据库 -->
-            <artifactId>jedis-mock</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>uk.co.jemos.podam</groupId> <!-- 单元测试,随机生成 POJO 类 -->
-            <artifactId>podam</artifactId>
-        </dependency>
-    </dependencies>
-</project>
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/config/RedisTestConfiguration.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/config/RedisTestConfiguration.java
deleted file mode 100644
index 1070768..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/config/RedisTestConfiguration.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.test.config;
-
-import com.github.fppt.jedismock.RedisServer;
-import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-
-import java.io.IOException;
-
-/**
- * Redis 测试 Configuration,主要实现内嵌 Redis 的启动
- *
- * @author iailab
- */
-@Configuration(proxyBeanMethods = false)
-@Lazy(false) // 禁止延迟加载
-@EnableConfigurationProperties(RedisProperties.class)
-public class RedisTestConfiguration {
-
-    /**
-     * 创建模拟的 Redis Server 服务器
-     */
-    @Bean
-    public RedisServer redisServer(RedisProperties properties) throws IOException {
-        RedisServer redisServer = new RedisServer(properties.getPort());
-        // 一次执行多个单元测试时,貌似创建多个 spring 容器,导致不进行 stop。这样,就导致端口被占用,无法启动。。。
-        try {
-            redisServer.start();
-        } catch (Exception ignore) {}
-        return redisServer;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/config/SqlInitializationTestConfiguration.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/config/SqlInitializationTestConfiguration.java
deleted file mode 100644
index 9703f2c..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/config/SqlInitializationTestConfiguration.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.iailab.framework.test.config;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
-import org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
-import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer;
-import org.springframework.boot.sql.init.DatabaseInitializationSettings;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-
-import javax.sql.DataSource;
-
-/**
- * SQL 初始化的测试 Configuration
- *
- * 为什么不使用 org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration 呢?
- * 因为我们在单元测试会使用 spring.main.lazy-initialization 为 true,开启延迟加载。此时,会导致 DataSourceInitializationConfiguration 初始化
- * 不过呢,当前类的实现代码,基本是复制 DataSourceInitializationConfiguration 的哈!
- *
- * @author iailab
- */
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnMissingBean(AbstractScriptDatabaseInitializer.class)
-@ConditionalOnSingleCandidate(DataSource.class)
-@ConditionalOnClass(name = "org.springframework.jdbc.datasource.init.DatabasePopulator")
-@Lazy(value = false) // 禁止延迟加载
-@EnableConfigurationProperties(SqlInitializationProperties.class)
-public class SqlInitializationTestConfiguration {
-
-	@Bean
-	public DataSourceScriptDatabaseInitializer dataSourceScriptDatabaseInitializer(DataSource dataSource,
-																				   SqlInitializationProperties initializationProperties) {
-		DatabaseInitializationSettings settings = createFrom(initializationProperties);
-		return new DataSourceScriptDatabaseInitializer(dataSource, settings);
-	}
-
-	static DatabaseInitializationSettings createFrom(SqlInitializationProperties properties) {
-		DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
-		settings.setSchemaLocations(properties.getSchemaLocations());
-		settings.setDataLocations(properties.getDataLocations());
-		settings.setContinueOnError(properties.isContinueOnError());
-		settings.setSeparator(properties.getSeparator());
-		settings.setEncoding(properties.getEncoding());
-		settings.setMode(properties.getMode());
-		return settings;
-	}
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseDbAndRedisUnitTest.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseDbAndRedisUnitTest.java
deleted file mode 100644
index 1c4b8d9..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseDbAndRedisUnitTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.iailab.framework.test.core.ut;
-
-import com.iailab.framework.datasource.config.IailabDataSourceAutoConfiguration;
-import com.iailab.framework.mybatis.config.IailabMybatisAutoConfiguration;
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import com.iailab.framework.test.config.RedisTestConfiguration;
-import com.iailab.framework.test.config.SqlInitializationTestConfiguration;
-import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
-import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
-import org.redisson.spring.starter.RedissonAutoConfiguration;
-import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Import;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.jdbc.Sql;
-
-/**
- * 依赖内存 DB + Redis 的单元测试
- *
- * 相比 {@link BaseDbUnitTest} 来说,额外增加了内存 Redis
- *
- * @author iailab
- */
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class)
-@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
-@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
-public class BaseDbAndRedisUnitTest {
-
-    @Import({
-            // DB 配置类
-            IailabDataSourceAutoConfiguration.class, // 自己的 DB 配置类
-            DataSourceAutoConfiguration.class, // Spring DB 自动配置类
-            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
-            DruidDataSourceAutoConfigure.class, // Druid 自动配置类
-            SqlInitializationTestConfiguration.class, // SQL 初始化
-            // MyBatis 配置类
-            IailabMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
-            MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
-
-            // Redis 配置类
-            RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
-            IailabRedisAutoConfiguration.class, // 自己的 Redis 配置类
-            RedisAutoConfiguration.class, // Spring Redis 自动配置类
-            RedissonAutoConfiguration.class, // Redisson 自动配置类
-    })
-    public static class Application {
-    }
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseDbUnitTest.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseDbUnitTest.java
deleted file mode 100644
index bd8d0f5..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseDbUnitTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.iailab.framework.test.core.ut;
-
-import com.iailab.framework.datasource.config.IailabDataSourceAutoConfiguration;
-import com.iailab.framework.mybatis.config.IailabMybatisAutoConfiguration;
-import com.iailab.framework.test.config.SqlInitializationTestConfiguration;
-import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
-import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
-import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Import;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.jdbc.Sql;
-
-/**
- * 依赖内存 DB 的单元测试
- *
- * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法
- *
- * @author iailab
- */
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class)
-@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
-@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
-public class BaseDbUnitTest {
-
-    @Import({
-            // DB 配置类
-            IailabDataSourceAutoConfiguration.class, // 自己的 DB 配置类
-            DataSourceAutoConfiguration.class, // Spring DB 自动配置类
-            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
-            DruidDataSourceAutoConfigure.class, // Druid 自动配置类
-            SqlInitializationTestConfiguration.class, // SQL 初始化
-            // MyBatis 配置类
-            IailabMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
-            MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
-            MybatisPlusJoinAutoConfiguration.class, // MyBatis 的Join配置类
-    })
-    public static class Application {
-    }
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseMockitoUnitTest.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseMockitoUnitTest.java
deleted file mode 100644
index 198c6d0..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseMockitoUnitTest.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.iailab.framework.test.core.ut;
-
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-/**
- * 纯 Mockito 的单元测试
- *
- * @author iailab
- */
-@ExtendWith(MockitoExtension.class)
-public class BaseMockitoUnitTest {
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseRedisUnitTest.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseRedisUnitTest.java
deleted file mode 100644
index dc1acd9..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/BaseRedisUnitTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.iailab.framework.test.core.ut;
-
-import com.iailab.framework.redis.config.IailabRedisAutoConfiguration;
-import com.iailab.framework.test.config.RedisTestConfiguration;
-import org.redisson.spring.starter.RedissonAutoConfiguration;
-import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Import;
-import org.springframework.test.context.ActiveProfiles;
-
-/**
- * 依赖内存 Redis 的单元测试
- *
- * 相比 {@link BaseDbUnitTest} 来说,从内存 DB 改成了内存 Redis
- *
- * @author iailab
- */
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisUnitTest.Application.class)
-@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
-public class BaseRedisUnitTest {
-
-    @Import({
-            // Redis 配置类
-            RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer
-            RedisAutoConfiguration.class, // Spring Redis 自动配置类
-            IailabRedisAutoConfiguration.class, // 自己的 Redis 配置类
-            RedissonAutoConfiguration.class, // Redisson 自动配置类
-    })
-    public static class Application {
-    }
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/package-info.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/package-info.java
deleted file mode 100644
index faa9f02..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/ut/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 提供单元测试 Unit Test 的基类
- */
-package com.iailab.framework.test.core.ut;
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/util/AssertUtils.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/util/AssertUtils.java
deleted file mode 100644
index db91b59..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/util/AssertUtils.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.iailab.framework.test.core.util;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.exception.ErrorCode;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.exception.util.ServiceExceptionUtil;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.function.Executable;
-
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.Objects;
-
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-/**
- * 单元测试,assert 断言工具类
- *
- * @author iailab
- */
-public class AssertUtils {
-
-    /**
-     * 比对两个对象的属性是否一致
-     *
-     * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略
-     *
-     * @param expected 期望对象
-     * @param actual 实际对象
-     * @param ignoreFields 忽略的属性数组
-     */
-    public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
-        Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
-        Arrays.stream(expectedFields).forEach(expectedField -> {
-            // 忽略 jacoco 自动生成的 $jacocoData 属性的情况
-            if (expectedField.isSynthetic()) {
-                return;
-            }
-            // 如果是忽略的属性,则不进行比对
-            if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
-                return;
-            }
-            // 忽略不存在的属性
-            Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName());
-            if (actualField == null) {
-                return;
-            }
-            // 比对
-            Assertions.assertEquals(
-                    ReflectUtil.getFieldValue(expected, expectedField),
-                    ReflectUtil.getFieldValue(actual, actualField),
-                    String.format("Field(%s) 不匹配", expectedField.getName())
-            );
-        });
-    }
-
-    /**
-     * 比对两个对象的属性是否一致
-     *
-     * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略
-     *
-     * @param expected 期望对象
-     * @param actual 实际对象
-     * @param ignoreFields 忽略的属性数组
-     * @return 是否一致
-     */
-    public static boolean isPojoEquals(Object expected, Object actual, String... ignoreFields) {
-        Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
-        return Arrays.stream(expectedFields).allMatch(expectedField -> {
-            // 如果是忽略的属性,则不进行比对
-            if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
-                return true;
-            }
-            // 忽略不存在的属性
-            Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName());
-            if (actualField == null) {
-                return true;
-            }
-            return Objects.equals(ReflectUtil.getFieldValue(expected, expectedField),
-                    ReflectUtil.getFieldValue(actual, actualField));
-        });
-    }
-
-    /**
-     * 执行方法,校验抛出的 Service 是否符合条件
-     *
-     * @param executable 业务异常
-     * @param errorCode 错误码对象
-     * @param messageParams 消息参数
-     */
-    public static void assertServiceException(Executable executable, ErrorCode errorCode, Object... messageParams) {
-        // 调用方法
-        ServiceException serviceException = assertThrows(ServiceException.class, executable);
-        // 校验错误码
-        Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配");
-        String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), messageParams);
-        Assertions.assertEquals(message, serviceException.getMessage(), "错误提示不匹配");
-    }
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/util/RandomUtils.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/util/RandomUtils.java
deleted file mode 100644
index 976786c..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/core/util/RandomUtils.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.iailab.framework.test.core.util;
-
-import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.RandomUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import uk.co.jemos.podam.api.PodamFactory;
-import uk.co.jemos.podam.api.PodamFactoryImpl;
-
-import java.lang.reflect.Type;
-import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * 随机工具类
- *
- * @author iailab
- */
-public class RandomUtils {
-
-    private static final int RANDOM_STRING_LENGTH = 10;
-
-    private static final int TINYINT_MAX = 127;
-
-    private static final int RANDOM_DATE_MAX = 30;
-
-    private static final int RANDOM_COLLECTION_LENGTH = 5;
-
-    private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl();
-
-    static {
-        // 字符串
-        PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class,
-                (dataProviderStrategy, attributeMetadata, map) -> randomString());
-        // Integer
-        PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Integer.class, (dataProviderStrategy, attributeMetadata, map) -> {
-            // 如果是 status 的字段,返回 0 或 1
-            if ("status".equals(attributeMetadata.getAttributeName())) {
-                return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus();
-            }
-            // 如果是 type、status 结尾的字段,返回 tinyint 范围
-            if (StrUtil.endWithAnyIgnoreCase(attributeMetadata.getAttributeName(),
-                    "type", "status", "category", "scope", "result")) {
-                return RandomUtil.randomInt(0, TINYINT_MAX + 1);
-            }
-            return RandomUtil.randomInt();
-        });
-        // LocalDateTime
-        PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class,
-                (dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime());
-        // Boolean
-        PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> {
-            // 如果是 deleted 的字段,返回非删除
-            if ("deleted".equals(attributeMetadata.getAttributeName())) {
-                return false;
-            }
-            return RandomUtil.randomBoolean();
-        });
-    }
-
-    public static String randomString() {
-        return RandomUtil.randomString(RANDOM_STRING_LENGTH);
-    }
-
-    public static Long randomLongId() {
-        return RandomUtil.randomLong(0, Long.MAX_VALUE);
-    }
-
-    public static Integer randomInteger() {
-        return RandomUtil.randomInt(0, Integer.MAX_VALUE);
-    }
-
-    public static Date randomDate() {
-        return RandomUtil.randomDay(0, RANDOM_DATE_MAX);
-    }
-
-    public static LocalDateTime randomLocalDateTime() {
-        // 设置 Nano 为零的原因,避免 MySQL、H2 存储不到时间戳
-        return LocalDateTimeUtil.of(randomDate()).withNano(0);
-    }
-
-    public static Short randomShort() {
-        return (short) RandomUtil.randomInt(0, Short.MAX_VALUE);
-    }
-
-    public static <T> Set<T> randomSet(Class<T> clazz) {
-        return Stream.iterate(0, i -> i).limit(RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH))
-                .map(i -> randomPojo(clazz)).collect(Collectors.toSet());
-    }
-
-    public static Integer randomCommonStatus() {
-        return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus();
-    }
-
-    public static String randomEmail() {
-        return randomString() + "@qq.com";
-    }
-
-    public static String randomURL() {
-        return "https://www.baidu.com/" + randomString();
-    }
-
-    @SafeVarargs
-    public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
-        T pojo = PODAM_FACTORY.manufacturePojo(clazz);
-        // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理
-        if (ArrayUtil.isNotEmpty(consumers)) {
-            Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo));
-        }
-        return pojo;
-    }
-
-    @SafeVarargs
-    public static <T> T randomPojo(Class<T> clazz, Type type, Consumer<T>... consumers) {
-        T pojo = PODAM_FACTORY.manufacturePojo(clazz, type);
-        // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理
-        if (ArrayUtil.isNotEmpty(consumers)) {
-            Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo));
-        }
-        return pojo;
-    }
-
-    @SafeVarargs
-    public static <T> List<T> randomPojoList(Class<T> clazz, Consumer<T>... consumers) {
-        int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH);
-        return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers))
-                .collect(Collectors.toList());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/package-info.java b/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/package-info.java
deleted file mode 100644
index ee6520a..0000000
--- a/iailab-framework/iailab-common-test/src/main/java/com/iailab/framework/test/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 测试组件,用于单元测试、集成测试等等
- */
-package com.iailab.framework.test;
diff --git a/iailab-framework/iailab-common-web/pom.xml b/iailab-framework/iailab-common-web/pom.xml
deleted file mode 100644
index 6fb1917..0000000
--- a/iailab-framework/iailab-common-web/pom.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-web</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>Web 框架,全局异常、API 日志、脱敏、错误码等</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>mybatis-plus-boot-starter</artifactId> <!-- 捕获mybatis全局异常 -->
-        </dependency>
-
-        <!-- Spring Boot 配置所需依赖 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-validation</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-core</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,主要是 GlobalExceptionHandler 使用 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
-            <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springdoc</groupId>  <!-- 接口文档 -->
-            <artifactId>springdoc-openapi-ui</artifactId>
-        </dependency>
-
-        <!-- RPC 远程调用相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-rpc</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- 业务组件 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-module-infra-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
-            <version>${revision}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-module-system-api</artifactId> <!-- 需要使用它,进行错误码的记录 -->
-            <version>${revision}</version>
-        </dependency>
-
-        <!-- xss -->
-        <dependency>
-            <groupId>org.jsoup</groupId>
-            <artifactId>jsoup</artifactId>
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-inline</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/config/IailabApiLogAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/config/IailabApiLogAutoConfiguration.java
deleted file mode 100644
index 8edd048..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/config/IailabApiLogAutoConfiguration.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.iailab.framework.apilog.config;
-
-import com.iailab.framework.apilog.core.filter.ApiAccessLogFilter;
-import com.iailab.framework.apilog.core.interceptor.ApiAccessLogInterceptor;
-import com.iailab.framework.apilog.core.service.ApiAccessLogFrameworkService;
-import com.iailab.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl;
-import com.iailab.framework.apilog.core.service.ApiErrorLogFrameworkService;
-import com.iailab.framework.apilog.core.service.ApiErrorLogFrameworkServiceImpl;
-import com.iailab.framework.common.enums.WebFilterOrderEnum;
-import com.iailab.framework.web.config.WebProperties;
-import com.iailab.framework.web.config.IailabWebAutoConfiguration;
-import com.iailab.module.infra.api.logger.ApiAccessLogApi;
-import com.iailab.module.infra.api.logger.ApiErrorLogApi;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-import javax.servlet.Filter;
-
-@AutoConfiguration(after = IailabWebAutoConfiguration.class)
-public class IailabApiLogAutoConfiguration implements WebMvcConfigurer {
-
-    @Bean
-    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
-    public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) {
-        return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi);
-    }
-
-    @Bean
-    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
-    public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) {
-        return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi);
-    }
-
-    /**
-     * 创建 ApiAccessLogFilter Bean,记录 API 请求日志
-     */
-    @Bean
-    @ConditionalOnProperty(prefix = "iailab.access-log", value = "enable", matchIfMissing = true) // 允许使用 iailab.access-log.enable=false 禁用访问日志
-    public FilterRegistrationBean<ApiAccessLogFilter> apiAccessLogFilter(WebProperties webProperties,
-                                                                         @Value("${spring.application.name}") String applicationName,
-                                                                         ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
-        ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService);
-        return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER);
-    }
-
-    private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
-        FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
-        bean.setOrder(order);
-        return bean;
-    }
-
-    @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-        registry.addInterceptor(new ApiAccessLogInterceptor());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/config/IailabApiLogRpcAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/config/IailabApiLogRpcAutoConfiguration.java
deleted file mode 100644
index acb5fee..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/config/IailabApiLogRpcAutoConfiguration.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.iailab.framework.apilog.config;
-
-import com.iailab.module.infra.api.logger.ApiAccessLogApi;
-import com.iailab.module.infra.api.logger.ApiErrorLogApi;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.cloud.openfeign.EnableFeignClients;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * API 日志使用到 Feign 的配置项
- *
- * @author iailab
- */
-@AutoConfiguration
-@EnableFeignClients(clients = {ApiAccessLogApi.class, // 主要是引入相关的 API 服务
-        ApiErrorLogApi.class})
-public class IailabApiLogRpcAutoConfiguration {
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/annotation/ApiAccessLog.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/annotation/ApiAccessLog.java
deleted file mode 100644
index d5ac165..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/annotation/ApiAccessLog.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.iailab.framework.apilog.core.annotation;
-
-import com.iailab.framework.apilog.core.enums.OperateTypeEnum;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 访问日志注解
- *
- * @author iailab
- */
-@Target({ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ApiAccessLog {
-
-    // ========== 开关字段 ==========
-
-    /**
-     * 是否记录访问日志
-     */
-    boolean enable() default true;
-    /**
-     * 是否记录请求参数
-     *
-     * 默认记录,主要考虑请求数据一般不大。可手动设置为 false 进行关闭
-     */
-    boolean requestEnable() default true;
-    /**
-     * 是否记录响应结果
-     *
-     * 默认不记录,主要考虑响应数据可能比较大。可手动设置为 true 进行打开
-     */
-    boolean responseEnable() default false;
-    /**
-     * 敏感参数数组
-     *
-     * 添加后,请求参数、响应结果不会记录该参数
-     */
-    String[] sanitizeKeys() default {};
-
-    // ========== 模块字段 ==========
-
-    /**
-     * 操作模块
-     *
-     * 为空时,会尝试读取 {@link io.swagger.v3.oas.annotations.tags.Tag#name()} 属性
-     */
-    String operateModule() default "";
-    /**
-     * 操作名
-     *
-     * 为空时,会尝试读取 {@link io.swagger.v3.oas.annotations.Operation#summary()} 属性
-     */
-    String operateName() default "";
-    /**
-     * 操作分类
-     *
-     * 实际并不是数组,因为枚举不能设置 null 作为默认值
-     */
-    OperateTypeEnum[] operateType() default {};
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/enums/OperateTypeEnum.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/enums/OperateTypeEnum.java
deleted file mode 100644
index a8fdc80..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/enums/OperateTypeEnum.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.iailab.framework.apilog.core.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 操作日志的操作类型
- *
- * @author ruoyi
- */
-@Getter
-@AllArgsConstructor
-public enum OperateTypeEnum {
-
-    /**
-     * 查询
-     */
-    GET(1),
-    /**
-     * 新增
-     */
-    CREATE(2),
-    /**
-     * 修改
-     */
-    UPDATE(3),
-    /**
-     * 删除
-     */
-    DELETE(4),
-    /**
-     * 导出
-     */
-    EXPORT(5),
-    /**
-     * 导入
-     */
-    IMPORT(6),
-    /**
-     * 其它
-     *
-     * 在无法归类时,可以选择使用其它。因为还有操作名可以进一步标识
-     */
-    OTHER(0);
-
-    /**
-     * 类型
-     */
-    private final Integer type;
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/filter/ApiAccessLogFilter.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/filter/ApiAccessLogFilter.java
deleted file mode 100644
index 773c55c..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/filter/ApiAccessLogFilter.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package com.iailab.framework.apilog.core.filter;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.BooleanUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
-import com.iailab.framework.apilog.core.enums.OperateTypeEnum;
-import com.iailab.framework.apilog.core.service.ApiAccessLogFrameworkService;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.common.util.monitor.TracerUtils;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.web.config.WebProperties;
-import com.iailab.framework.web.core.filter.ApiRequestFilter;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import com.iailab.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
-import com.fasterxml.jackson.databind.JsonNode;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.method.HandlerMethod;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.time.temporal.ChronoUnit;
-import java.util.Iterator;
-import java.util.Map;
-
-import static com.iailab.framework.apilog.core.interceptor.ApiAccessLogInterceptor.*;
-import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
-
-/**
- * API 访问日志 Filter
- *
- * 目的:记录 API 访问日志到数据库中
- *
- * @author iailab
- */
-@Slf4j
-public class ApiAccessLogFilter extends ApiRequestFilter {
-
-    private static final String[] SANITIZE_KEYS = new String[]{"password", "token", "accessToken", "refreshToken"};
-
-    private final String applicationName;
-
-    private final ApiAccessLogFrameworkService apiAccessLogFrameworkService;
-
-    public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
-        super(webProperties);
-        this.applicationName = applicationName;
-        this.apiAccessLogFrameworkService = apiAccessLogFrameworkService;
-    }
-
-    @Override
-    @SuppressWarnings("NullableProblems")
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-            throws ServletException, IOException {
-        // 获得开始时间
-        LocalDateTime beginTime = LocalDateTime.now();
-        // 提前获得参数,避免 XssFilter 过滤处理
-        Map<String, String> queryString = ServletUtils.getParamMap(request);
-        String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null;
-
-        try {
-            // 继续过滤器
-            filterChain.doFilter(request, response);
-            // 正常执行,记录日志
-            createApiAccessLog(request, beginTime, queryString, requestBody, null);
-        } catch (Exception ex) {
-            // 异常执行,记录日志
-            createApiAccessLog(request, beginTime, queryString, requestBody, ex);
-            throw ex;
-        }
-    }
-
-    private void createApiAccessLog(HttpServletRequest request, LocalDateTime beginTime,
-                                    Map<String, String> queryString, String requestBody, Exception ex) {
-        ApiAccessLogCreateReqDTO accessLog = new ApiAccessLogCreateReqDTO();
-        try {
-            boolean enable = buildApiAccessLog(accessLog, request, beginTime, queryString, requestBody, ex);
-            if (!enable) {
-                return;
-            }
-            apiAccessLogFrameworkService.createApiAccessLog(accessLog);
-        } catch (Throwable th) {
-            log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th);
-        }
-    }
-
-    private boolean buildApiAccessLog(ApiAccessLogCreateReqDTO accessLog, HttpServletRequest request, LocalDateTime beginTime,
-                                      Map<String, String> queryString, String requestBody, Exception ex) {
-        // 判断:是否要记录操作日志
-        HandlerMethod handlerMethod = (HandlerMethod) request.getAttribute(ATTRIBUTE_HANDLER_METHOD);
-        ApiAccessLog accessLogAnnotation = null;
-        if (handlerMethod != null) {
-            accessLogAnnotation = handlerMethod.getMethodAnnotation(ApiAccessLog.class);
-            if (accessLogAnnotation != null && BooleanUtil.isFalse(accessLogAnnotation.enable())) {
-                return false;
-            }
-        }
-
-        // 处理用户信息
-        accessLog.setUserId(WebFrameworkUtils.getLoginUserId(request))
-                .setUserType(WebFrameworkUtils.getLoginUserType(request));
-        // 设置访问结果
-        CommonResult<?> result = WebFrameworkUtils.getCommonResult(request);
-        if (result != null) {
-            accessLog.setResultCode(result.getCode()).setResultMsg(result.getMsg());
-        } else if (ex != null) {
-            accessLog.setResultCode(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode())
-                    .setResultMsg(ExceptionUtil.getRootCauseMessage(ex));
-        } else {
-            accessLog.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()).setResultMsg("");
-        }
-        // 设置请求字段
-        accessLog.setTraceId(TracerUtils.getTraceId()).setApplicationName(applicationName)
-                .setRequestUrl(request.getRequestURI()).setRequestMethod(request.getMethod())
-                .setUserAgent(ServletUtils.getUserAgent(request)).setUserIp(ServletUtils.getClientIP(request));
-        String[] sanitizeKeys = accessLogAnnotation != null ? accessLogAnnotation.sanitizeKeys() : null;
-        Boolean requestEnable = accessLogAnnotation != null ? accessLogAnnotation.requestEnable() : Boolean.TRUE;
-        if (!BooleanUtil.isFalse(requestEnable)) { // 默认记录,所以判断 !false
-            Map<String, Object> requestParams = MapUtil.<String, Object>builder()
-                    .put("query", sanitizeMap(queryString, sanitizeKeys))
-                    .put("body", sanitizeJson(requestBody, sanitizeKeys)).build();
-            accessLog.setRequestParams(toJsonString(requestParams));
-        }
-        Boolean responseEnable = accessLogAnnotation != null ? accessLogAnnotation.responseEnable() : Boolean.FALSE;
-        if (BooleanUtil.isTrue(responseEnable)) { // 默认不记录,默认强制要求 true
-            accessLog.setResponseBody(sanitizeJson(result, sanitizeKeys));
-        }
-        // 持续时间
-        accessLog.setBeginTime(beginTime).setEndTime(LocalDateTime.now())
-                .setDuration((int) LocalDateTimeUtil.between(accessLog.getBeginTime(), accessLog.getEndTime(), ChronoUnit.MILLIS));
-
-        // 操作模块
-        if (handlerMethod != null) {
-            Tag tagAnnotation = handlerMethod.getBeanType().getAnnotation(Tag.class);
-            Operation operationAnnotation = handlerMethod.getMethodAnnotation(Operation.class);
-            String operateModule = accessLogAnnotation != null ? accessLogAnnotation.operateModule() :
-                    tagAnnotation != null ? StrUtil.nullToDefault(tagAnnotation.name(), tagAnnotation.description()) : null;
-            String operateName = accessLogAnnotation != null ? accessLogAnnotation.operateName() :
-                    operationAnnotation != null ? operationAnnotation.summary() : null;
-            OperateTypeEnum operateType = accessLogAnnotation != null && accessLogAnnotation.operateType().length > 0 ?
-                    accessLogAnnotation.operateType()[0] : parseOperateLogType(request);
-            accessLog.setOperateModule(operateModule).setOperateName(operateName).setOperateType(operateType.getType());
-        }
-        return true;
-    }
-
-    // ========== 解析 @ApiAccessLog、@Swagger 注解  ==========
-
-    private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) {
-        RequestMethod requestMethod = ArrayUtil.firstMatch(method ->
-                StrUtil.equalsAnyIgnoreCase(method.name(), request.getMethod()), RequestMethod.values());
-        if (requestMethod == null) {
-            return OperateTypeEnum.OTHER;
-        }
-        switch (requestMethod) {
-            case GET:
-                return OperateTypeEnum.GET;
-            case POST:
-                return OperateTypeEnum.CREATE;
-            case PUT:
-                return OperateTypeEnum.UPDATE;
-            case DELETE:
-                return OperateTypeEnum.DELETE;
-            default:
-                return OperateTypeEnum.OTHER;
-        }
-    }
-
-    // ========== 请求和响应的脱敏逻辑,移除类似 password、token 等敏感字段 ==========
-
-    private static String sanitizeMap(Map<String, ?> map, String[] sanitizeKeys) {
-        if (CollUtil.isNotEmpty(map)) {
-            return null;
-        }
-        if (sanitizeKeys != null) {
-            MapUtil.removeAny(map, sanitizeKeys);
-        }
-        MapUtil.removeAny(map, SANITIZE_KEYS);
-        return JsonUtils.toJsonString(map);
-    }
-
-    private static String sanitizeJson(String jsonString, String[] sanitizeKeys) {
-        if (StrUtil.isEmpty(jsonString)) {
-            return null;
-        }
-        try {
-            JsonNode rootNode = JsonUtils.parseTree(jsonString);
-            sanitizeJson(rootNode, sanitizeKeys);
-            return JsonUtils.toJsonString(rootNode);
-        } catch (Exception e) {
-            // 脱敏失败的情况下,直接忽略异常,避免影响用户请求
-            log.error("[sanitizeJson][脱敏({}) 发生异常]", jsonString, e);
-            return jsonString;
-        }
-    }
-
-    private static String sanitizeJson(CommonResult<?> commonResult, String[] sanitizeKeys) {
-        if (commonResult == null) {
-            return null;
-        }
-        String jsonString = toJsonString(commonResult);
-        try {
-            JsonNode rootNode = JsonUtils.parseTree(jsonString);
-            sanitizeJson(rootNode.get("data"), sanitizeKeys); // 只处理 data 字段,不处理 code、msg 字段,避免错误被脱敏掉
-            return JsonUtils.toJsonString(rootNode);
-        } catch (Exception e) {
-            // 脱敏失败的情况下,直接忽略异常,避免影响用户请求
-            log.error("[sanitizeJson][脱敏({}) 发生异常]", jsonString, e);
-            return jsonString;
-        }
-    }
-
-    private static void sanitizeJson(JsonNode node, String[] sanitizeKeys) {
-        // 情况一:数组,遍历处理
-        if (node.isArray()) {
-            for (JsonNode childNode : node) {
-                sanitizeJson(childNode, sanitizeKeys);
-            }
-            return;
-        }
-        // 情况二:非 Object,只是某个值,直接返回
-        if (!node.isObject()) {
-            return;
-        }
-        //  情况三:Object,遍历处理
-        Iterator<Map.Entry<String, JsonNode>> iterator = node.fields();
-        while (iterator.hasNext()) {
-            Map.Entry<String, JsonNode> entry = iterator.next();
-            if (ArrayUtil.contains(sanitizeKeys, entry.getKey())
-                    || ArrayUtil.contains(SANITIZE_KEYS, entry.getKey())) {
-                iterator.remove();
-                continue;
-            }
-            sanitizeJson(entry.getValue(), sanitizeKeys);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java
deleted file mode 100644
index f22500a..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.iailab.framework.apilog.core.interceptor;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.resource.ResourceUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.common.util.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.StopWatch;
-import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.HandlerInterceptor;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.IntStream;
-
-/**
- * API 访问日志 Interceptor
- *
- * 目的:在非 prod 环境时,打印 request 和 response 两条日志到日志文件(控制台)中。
- *
- * @author iailab
- */
-@Slf4j
-public class ApiAccessLogInterceptor implements HandlerInterceptor {
-
-    public static final String ATTRIBUTE_HANDLER_METHOD = "HANDLER_METHOD";
-
-    private static final String ATTRIBUTE_STOP_WATCH = "ApiAccessLogInterceptor.StopWatch";
-
-    @Override
-    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
-        // 记录 HandlerMethod,提供给 ApiAccessLogFilter 使用
-        HandlerMethod handlerMethod = handler instanceof HandlerMethod ? (HandlerMethod) handler : null;
-        if (handlerMethod != null) {
-            request.setAttribute(ATTRIBUTE_HANDLER_METHOD, handlerMethod);
-        }
-
-        // 打印 request 日志
-        if (!SpringUtils.isProd()) {
-            Map<String, String> queryString = ServletUtils.getParamMap(request);
-            String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null;
-            if (CollUtil.isEmpty(queryString) && StrUtil.isEmpty(requestBody)) {
-                log.info("[preHandle][开始请求 URL({}) 无参数]", request.getRequestURI());
-            } else {
-                log.info("[preHandle][开始请求 URL({}) 参数({})]", request.getRequestURI(),
-                        StrUtil.blankToDefault(requestBody, queryString.toString()));
-            }
-            // 计时
-            StopWatch stopWatch = new StopWatch();
-            stopWatch.start();
-            request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch);
-            // 打印 Controller 路径
-            printHandlerMethodPosition(handlerMethod);
-        }
-        return true;
-    }
-
-    @Override
-    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
-        // 打印 response 日志
-        if (!SpringUtils.isProd()) {
-            StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH);
-            stopWatch.stop();
-            log.info("[afterCompletion][完成请求 URL({}) 耗时({} ms)]",
-                    request.getRequestURI(), stopWatch.getTotalTimeMillis());
-        }
-    }
-
-    /**
-     * 打印 Controller 方法路径
-     */
-    private void printHandlerMethodPosition(HandlerMethod handlerMethod) {
-        if (handlerMethod == null) {
-            return;
-        }
-        Method method = handlerMethod.getMethod();
-        Class<?> clazz = method.getDeclaringClass();
-        try {
-            // 获取 method 的 lineNumber
-            List<String> clazzContents = FileUtil.readUtf8Lines(
-                    ResourceUtil.getResource(null, clazz).getPath().replace("/target/classes/", "/src/main/java/")
-                            + clazz.getSimpleName() + ".java");
-            Optional<Integer> lineNumber = IntStream.range(0, clazzContents.size())
-                    .filter(i -> clazzContents.get(i).contains(" " + method.getName() + "(")) // 简单匹配,不考虑方法重名
-                    .mapToObj(i -> i + 1) // 行号从 1 开始
-                    .findFirst();
-            if (!lineNumber.isPresent()) {
-                return;
-            }
-            // 打印结果
-            System.out.printf("\tController 方法路径:%s(%s.java:%d)\n", clazz.getName(), clazz.getSimpleName(), lineNumber.get());
-        } catch (Exception ignore) {
-            // 忽略异常。原因:仅仅打印,非重要逻辑
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiAccessLogFrameworkService.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiAccessLogFrameworkService.java
deleted file mode 100644
index 6793b93..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiAccessLogFrameworkService.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.framework.apilog.core.service;
-
-import com.iailab.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
-
-/**
- * API 访问日志 Framework Service 接口
- *
- * @author iailab
- */
-public interface ApiAccessLogFrameworkService {
-
-    /**
-     * 创建 API 访问日志
-     *
-     * @param reqDTO API 访问日志
-     */
-    void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO);
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java
deleted file mode 100644
index 82501a5..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.iailab.framework.apilog.core.service;
-
-import com.iailab.module.infra.api.logger.ApiAccessLogApi;
-import com.iailab.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Async;
-
-/**
- * API 访问日志 Framework Service 实现类
- *
- * 基于 {@link ApiAccessLogApi} 服务,记录访问日志
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-@Slf4j
-public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkService {
-
-    private final ApiAccessLogApi apiAccessLogApi;
-
-    @Override
-    @Async
-    public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) {
-        try {
-            apiAccessLogApi.createApiAccessLog(reqDTO);
-        } catch (Throwable ex) {
-            // 由于 @Async 异步调用,这里打印下日志,更容易跟进
-            log.error("[createApiAccessLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiErrorLogFrameworkService.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiErrorLogFrameworkService.java
deleted file mode 100644
index 43ac23e..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiErrorLogFrameworkService.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.framework.apilog.core.service;
-
-import com.iailab.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
-
-/**
- * API 错误日志 Framework Service 接口
- *
- * @author iailab
- */
-public interface ApiErrorLogFrameworkService {
-
-    /**
-     * 创建 API 错误日志
-     *
-     * @param reqDTO API 错误日志
-     */
-    void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO);
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java
deleted file mode 100644
index 87055ce..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.iailab.framework.apilog.core.service;
-
-import com.iailab.module.infra.api.logger.ApiErrorLogApi;
-import com.iailab.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Async;
-
-/**
- * API 错误日志 Framework Service 实现类
- *
- * 基于 {@link ApiErrorLogApi} 服务,记录错误日志
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-@Slf4j
-public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkService {
-
-    private final ApiErrorLogApi apiErrorLogApi;
-
-    @Override
-    @Async
-    public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) {
-        try {
-            apiErrorLogApi.createApiErrorLog(reqDTO);
-        } catch (Throwable ex) {
-            // 由于 @Async 异步调用,这里打印下日志,更容易跟进
-            log.error("[createApiErrorLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/package-info.java
deleted file mode 100644
index 4dec8e5..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/package-info.java
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * API 日志:包含两类
- * 1. API 访问日志:记录用户访问 API 的访问日志,定期归档历史日志。
- * 2. 异常日志:记录用户访问 API 的系统异常,方便日常排查问题与告警。
- *
- * @author iailab
- */
-package com.iailab.framework.apilog;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/config/IailabBannerAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/config/IailabBannerAutoConfiguration.java
deleted file mode 100644
index ae7abfc..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/config/IailabBannerAutoConfiguration.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.iailab.framework.banner.config;
-
-import com.iailab.framework.banner.core.BannerApplicationRunner;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-
-/**
- * Banner 的自动配置类
- *
- * @author iailab
- */
-@AutoConfiguration
-public class IailabBannerAutoConfiguration {
-
-    @Bean
-    public BannerApplicationRunner bannerApplicationRunner() {
-        return new BannerApplicationRunner();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/core/BannerApplicationRunner.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/core/BannerApplicationRunner.java
deleted file mode 100644
index fd4c918..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/core/BannerApplicationRunner.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.banner.core;
-
-import cn.hutool.core.thread.ThreadUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 项目启动成功后,提供文档相关的地址
- *
- * @author iailab
- */
-@Slf4j
-public class BannerApplicationRunner implements ApplicationRunner {
-
-    @Override
-    public void run(ApplicationArguments args) {
-        ThreadUtil.execute(() -> {
-            ThreadUtil.sleep(1, TimeUnit.SECONDS); // 延迟 1 秒,保证输出到结尾
-            log.info("\n----------------------------------------------------------\n\t" +
-                            "项目启动成功!\n\t" +
-                            "----------------------------------------------------------");
-        });
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/package-info.java
deleted file mode 100644
index 8567532..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/banner/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Banner 用于在 console 控制台,打印开发文档、接口文档等
- *
- * @author iailab
- */
-package com.iailab.framework.banner;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/annotation/DesensitizeBy.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/annotation/DesensitizeBy.java
deleted file mode 100644
index 1894a51..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/annotation/DesensitizeBy.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.iailab.framework.desensitize.core.base.annotation;
-
-import com.iailab.framework.desensitize.core.base.handler.DesensitizationHandler;
-import com.iailab.framework.desensitize.core.base.serializer.StringDesensitizeSerializer;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 顶级脱敏注解,自定义注解需要使用此注解
- *
- * @author gaibu
- */
-@Documented
-@Target(ElementType.ANNOTATION_TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside // 此注解是其他所有 jackson 注解的元注解,打上了此注解的注解表明是 jackson 注解的一部分
-@JsonSerialize(using = StringDesensitizeSerializer.class) // 指定序列化器
-public @interface DesensitizeBy {
-
-    /**
-     * 脱敏处理器
-     */
-    @SuppressWarnings("rawtypes")
-    Class<? extends DesensitizationHandler> handler();
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/handler/DesensitizationHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/handler/DesensitizationHandler.java
deleted file mode 100644
index a761c0e..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/handler/DesensitizationHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.framework.desensitize.core.base.handler;
-
-import java.lang.annotation.Annotation;
-
-/**
- * 脱敏处理器接口
- *
- * @author gaibu
- */
-public interface DesensitizationHandler<T extends Annotation> {
-
-    /**
-     * 脱敏
-     *
-     * @param origin     原始字符串
-     * @param annotation 注解信息
-     * @return 脱敏后的字符串
-     */
-    String desensitize(String origin, T annotation);
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java
deleted file mode 100644
index 2d737f9..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.iailab.framework.desensitize.core.base.serializer;
-
-import cn.hutool.core.annotation.AnnotationUtil;
-import cn.hutool.core.lang.Singleton;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ReflectUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.base.handler.DesensitizationHandler;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.BeanProperty;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.ContextualSerializer;
-import com.fasterxml.jackson.databind.ser.std.StdSerializer;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.io.IOException;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-
-/**
- * 脱敏序列化器
- *
- * 实现 JSON 返回数据时,使用 {@link DesensitizationHandler} 对声明脱敏注解的字段,进行脱敏处理。
- *
- * @author gaibu
- */
-@SuppressWarnings("rawtypes")
-public class StringDesensitizeSerializer extends StdSerializer<String> implements ContextualSerializer {
-
-    @Getter
-    @Setter
-    private DesensitizationHandler desensitizationHandler;
-
-    protected StringDesensitizeSerializer() {
-        super(String.class);
-    }
-
-    @Override
-    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) {
-        DesensitizeBy annotation = beanProperty.getAnnotation(DesensitizeBy.class);
-        if (annotation == null) {
-            return this;
-        }
-        // 创建一个 StringDesensitizeSerializer 对象,使用 DesensitizeBy 对应的处理器
-        StringDesensitizeSerializer serializer = new StringDesensitizeSerializer();
-        serializer.setDesensitizationHandler(Singleton.get(annotation.handler()));
-        return serializer;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public void serialize(String value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException {
-        if (StrUtil.isBlank(value)) {
-            gen.writeNull();
-            return;
-        }
-        // 获取序列化字段
-        Field field = getField(gen);
-
-        // 自定义处理器
-        DesensitizeBy[] annotations = AnnotationUtil.getCombinationAnnotations(field, DesensitizeBy.class);
-        if (ArrayUtil.isEmpty(annotations)) {
-            gen.writeString(value);
-            return;
-        }
-        for (Annotation annotation : field.getAnnotations()) {
-            if (AnnotationUtil.hasAnnotation(annotation.annotationType(), DesensitizeBy.class)) {
-                value = this.desensitizationHandler.desensitize(value, annotation);
-                gen.writeString(value);
-                return;
-            }
-        }
-        gen.writeString(value);
-    }
-
-    /**
-     * 获取字段
-     *
-     * @param generator JsonGenerator
-     * @return 字段
-     */
-    private Field getField(JsonGenerator generator) {
-        String currentName = generator.getOutputContext().getCurrentName();
-        Object currentValue = generator.getCurrentValue();
-        Class<?> currentValueClass = currentValue.getClass();
-        return ReflectUtil.getField(currentValueClass, currentName);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/annotation/EmailDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/annotation/EmailDesensitize.java
deleted file mode 100644
index 65d31f4..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/annotation/EmailDesensitize.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.desensitize.core.regex.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.regex.handler.EmailDesensitizationHandler;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 邮箱脱敏注解
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = EmailDesensitizationHandler.class)
-public @interface EmailDesensitize {
-
-    /**
-     * 匹配的正则表达式
-     */
-    String regex() default "(^.)[^@]*(@.*$)";
-
-    /**
-     * 替换规则,邮箱;
-     *
-     * 比如:example@gmail.com 脱敏之后为 e****@gmail.com
-     */
-    String replacer() default "$1****$2";
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/annotation/RegexDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/annotation/RegexDesensitize.java
deleted file mode 100644
index 072a6ed..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/annotation/RegexDesensitize.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.iailab.framework.desensitize.core.regex.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.regex.handler.DefaultRegexDesensitizationHandler;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 正则脱敏注解
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = DefaultRegexDesensitizationHandler.class)
-public @interface RegexDesensitize {
-
-    /**
-     * 匹配的正则表达式(默认匹配所有)
-     */
-    String regex() default "^[\\s\\S]*$";
-
-    /**
-     * 替换规则,会将匹配到的字符串全部替换成 replacer
-     *
-     * 例如:regex=123; replacer=******
-     * 原始字符串 123456789
-     * 脱敏后字符串 ******456789
-     */
-    String replacer() default "******";
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java
deleted file mode 100644
index c5ecf05..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.iailab.framework.desensitize.core.regex.handler;
-
-import com.iailab.framework.desensitize.core.base.handler.DesensitizationHandler;
-
-import java.lang.annotation.Annotation;
-
-/**
- * 正则表达式脱敏处理器抽象类,已实现通用的方法
- *
- * @author gaibu
- */
-public abstract class AbstractRegexDesensitizationHandler<T extends Annotation>
-        implements DesensitizationHandler<T> {
-
-    @Override
-    public String desensitize(String origin, T annotation) {
-        String regex = getRegex(annotation);
-        String replacer = getReplacer(annotation);
-        return origin.replaceAll(regex, replacer);
-    }
-
-    /**
-     * 获取注解上的 regex 参数
-     *
-     * @param annotation 注解信息
-     * @return 正则表达式
-     */
-    abstract String getRegex(T annotation);
-
-    /**
-     * 获取注解上的 replacer 参数
-     *
-     * @param annotation 注解信息
-     * @return 待替换的字符串
-     */
-    abstract String getReplacer(T annotation);
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java
deleted file mode 100644
index 7adee18..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.framework.desensitize.core.regex.handler;
-
-import com.iailab.framework.desensitize.core.regex.annotation.RegexDesensitize;
-
-/**
- * {@link RegexDesensitize} 的正则脱敏处理器
- *
- * @author gaibu
- */
-public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitizationHandler<RegexDesensitize> {
-
-    @Override
-    String getRegex(RegexDesensitize annotation) {
-        return annotation.regex();
-    }
-
-    @Override
-    String getReplacer(RegexDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java
deleted file mode 100644
index 6b4d60b..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.desensitize.core.regex.handler;
-
-import com.iailab.framework.desensitize.core.regex.annotation.EmailDesensitize;
-
-/**
- * {@link EmailDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class EmailDesensitizationHandler extends AbstractRegexDesensitizationHandler<EmailDesensitize> {
-
-    @Override
-    String getRegex(EmailDesensitize annotation) {
-        return annotation.regex();
-    }
-
-    @Override
-    String getReplacer(EmailDesensitize annotation) {
-        return annotation.replacer();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/BankCardDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/BankCardDesensitize.java
deleted file mode 100644
index 67d3d9c..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/BankCardDesensitize.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.BankCardDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 银行卡号
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = BankCardDesensitization.class)
-public @interface BankCardDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 6;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 2;
-
-    /**
-     * 替换规则,银行卡号; 比如:9988002866797031 脱敏之后为 998800********31
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java
deleted file mode 100644
index ff33308..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.CarLicenseDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 车牌号
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = CarLicenseDesensitization.class)
-public @interface CarLicenseDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 3;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 1;
-
-    /**
-     * 替换规则,车牌号;比如:粤A66666 脱敏之后为粤A6***6
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java
deleted file mode 100644
index 7bf7094..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.ChineseNameDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 中文名
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = ChineseNameDesensitization.class)
-public @interface ChineseNameDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 1;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 0;
-
-    /**
-     * 替换规则,中文名;比如:刘子豪脱敏之后为刘**
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java
deleted file mode 100644
index b43a1ff..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.FixedPhoneDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 固定电话
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = FixedPhoneDesensitization.class)
-public @interface FixedPhoneDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 4;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 2;
-
-    /**
-     * 替换规则,固定电话;比如:01086551122 脱敏之后为 0108*****22
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/IdCardDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/IdCardDesensitize.java
deleted file mode 100644
index dde01ba..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/IdCardDesensitize.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.IdCardDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 身份证
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = IdCardDesensitization.class)
-public @interface IdCardDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 6;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 2;
-
-    /**
-     * 替换规则,身份证号码;比如:530321199204074611 脱敏之后为 530321**********11
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/MobileDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/MobileDesensitize.java
deleted file mode 100644
index 5de127f..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/MobileDesensitize.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.MobileDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 手机号
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = MobileDesensitization.class)
-public @interface MobileDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 3;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 4;
-
-    /**
-     * 替换规则,手机号;比如:13248765917 脱敏之后为 132****5917
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/PasswordDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/PasswordDesensitize.java
deleted file mode 100644
index 6b5ba79..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/PasswordDesensitize.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.PasswordDesensitization;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 密码
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = PasswordDesensitization.class)
-public @interface PasswordDesensitize {
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 0;
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 0;
-
-    /**
-     * 替换规则,密码;
-     *
-     * 比如:123456 脱敏之后为 ******
-     */
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/SliderDesensitize.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/SliderDesensitize.java
deleted file mode 100644
index c655d4e..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/annotation/SliderDesensitize.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.annotation;
-
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.slider.handler.DefaultDesensitizationHandler;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 滑动脱敏注解
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = DefaultDesensitizationHandler.class)
-public @interface SliderDesensitize {
-
-    /**
-     * 后缀保留长度
-     */
-    int suffixKeep() default 0;
-
-    /**
-     * 替换规则,会将前缀后缀保留后,全部替换成 replacer
-     *
-     * 例如:prefixKeep = 1; suffixKeep = 2; replacer = "*";
-     * 原始字符串  123456
-     * 脱敏后     1***56
-     */
-    String replacer() default "*";
-
-    /**
-     * 前缀保留长度
-     */
-    int prefixKeep() default 0;
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java
deleted file mode 100644
index 160fa15..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.base.handler.DesensitizationHandler;
-
-import java.lang.annotation.Annotation;
-
-/**
- * 滑动脱敏处理器抽象类,已实现通用的方法
- *
- * @author gaibu
- */
-public abstract class AbstractSliderDesensitizationHandler<T extends Annotation>
-        implements DesensitizationHandler<T> {
-
-    @Override
-    public String desensitize(String origin, T annotation) {
-        int prefixKeep = getPrefixKeep(annotation);
-        int suffixKeep = getSuffixKeep(annotation);
-        String replacer = getReplacer(annotation);
-        int length = origin.length();
-
-        // 情况一:原始字符串长度小于等于保留长度,则原始字符串全部替换
-        if (prefixKeep >= length || suffixKeep >= length) {
-            return buildReplacerByLength(replacer, length);
-        }
-
-        // 情况二:原始字符串长度小于等于前后缀保留字符串长度,则原始字符串全部替换
-        if ((prefixKeep + suffixKeep) >= length) {
-            return buildReplacerByLength(replacer, length);
-        }
-
-        // 情况三:原始字符串长度大于前后缀保留字符串长度,则替换中间字符串
-        int interval = length - prefixKeep - suffixKeep;
-        return origin.substring(0, prefixKeep) +
-                buildReplacerByLength(replacer, interval) +
-                origin.substring(prefixKeep + interval);
-    }
-
-    /**
-     * 根据长度循环构建替换符
-     *
-     * @param replacer 替换符
-     * @param length   长度
-     * @return 构建后的替换符
-     */
-    private String buildReplacerByLength(String replacer, int length) {
-        StringBuilder builder = new StringBuilder();
-        for (int i = 0; i < length; i++) {
-            builder.append(replacer);
-        }
-        return builder.toString();
-    }
-
-    /**
-     * 前缀保留长度
-     *
-     * @param annotation 注解信息
-     * @return 前缀保留长度
-     */
-    abstract Integer getPrefixKeep(T annotation);
-
-    /**
-     * 后缀保留长度
-     *
-     * @param annotation 注解信息
-     * @return 后缀保留长度
-     */
-    abstract Integer getSuffixKeep(T annotation);
-
-    /**
-     * 替换符
-     *
-     * @param annotation 注解信息
-     * @return 替换符
-     */
-    abstract String getReplacer(T annotation);
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/BankCardDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/BankCardDesensitization.java
deleted file mode 100644
index 64a3215..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/BankCardDesensitization.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.BankCardDesensitize;
-
-/**
- * {@link BankCardDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class BankCardDesensitization extends AbstractSliderDesensitizationHandler<BankCardDesensitize> {
-
-    @Override
-    Integer getPrefixKeep(BankCardDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(BankCardDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(BankCardDesensitize annotation) {
-        return annotation.replacer();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java
deleted file mode 100644
index 0280f99..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.CarLicenseDesensitize;
-
-/**
- * {@link CarLicenseDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class CarLicenseDesensitization extends AbstractSliderDesensitizationHandler<CarLicenseDesensitize> {
-    @Override
-    Integer getPrefixKeep(CarLicenseDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(CarLicenseDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(CarLicenseDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java
deleted file mode 100644
index 0eb5bc2..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.ChineseNameDesensitize;
-
-/**
- * {@link ChineseNameDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class ChineseNameDesensitization extends AbstractSliderDesensitizationHandler<ChineseNameDesensitize> {
-
-    @Override
-    Integer getPrefixKeep(ChineseNameDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(ChineseNameDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(ChineseNameDesensitize annotation) {
-        return annotation.replacer();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java
deleted file mode 100644
index 9b9f2bb..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.SliderDesensitize;
-
-/**
- * {@link SliderDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class DefaultDesensitizationHandler extends AbstractSliderDesensitizationHandler<SliderDesensitize> {
-    @Override
-    Integer getPrefixKeep(SliderDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(SliderDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(SliderDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java
deleted file mode 100644
index 53e44f3..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize;
-
-/**
- * {@link FixedPhoneDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHandler<FixedPhoneDesensitize> {
-    @Override
-    Integer getPrefixKeep(FixedPhoneDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(FixedPhoneDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(FixedPhoneDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/IdCardDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/IdCardDesensitization.java
deleted file mode 100644
index fde3851..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/IdCardDesensitization.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.IdCardDesensitize;
-
-/**
- * {@link IdCardDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class IdCardDesensitization extends AbstractSliderDesensitizationHandler<IdCardDesensitize> {
-    @Override
-    Integer getPrefixKeep(IdCardDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(IdCardDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(IdCardDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/MobileDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/MobileDesensitization.java
deleted file mode 100644
index 26216aa..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/MobileDesensitization.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.MobileDesensitize;
-
-/**
- * {@link MobileDesensitize} 的脱敏处理器
- *
- * @author gaibu
- */
-public class MobileDesensitization extends AbstractSliderDesensitizationHandler<MobileDesensitize> {
-
-    @Override
-    Integer getPrefixKeep(MobileDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(MobileDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(MobileDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/PasswordDesensitization.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/PasswordDesensitization.java
deleted file mode 100644
index 55dfc56..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/core/slider/handler/PasswordDesensitization.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.desensitize.core.slider.handler;
-
-import com.iailab.framework.desensitize.core.slider.annotation.PasswordDesensitize;
-
-/**
- * {@link PasswordDesensitize} 的码脱敏处理器
- *
- * @author gaibu
- */
-public class PasswordDesensitization extends AbstractSliderDesensitizationHandler<PasswordDesensitize> {
-    @Override
-    Integer getPrefixKeep(PasswordDesensitize annotation) {
-        return annotation.prefixKeep();
-    }
-
-    @Override
-    Integer getSuffixKeep(PasswordDesensitize annotation) {
-        return annotation.suffixKeep();
-    }
-
-    @Override
-    String getReplacer(PasswordDesensitize annotation) {
-        return annotation.replacer();
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/package-info.java
deleted file mode 100644
index 0634924..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/desensitize/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏
- */
-package com.iailab.framework.desensitize;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/config/IailabJacksonAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/config/IailabJacksonAutoConfiguration.java
deleted file mode 100644
index 713525c..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/config/IailabJacksonAutoConfiguration.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.iailab.framework.jackson.config;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
-import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
-import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
-import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
-import com.iailab.framework.common.util.json.databind.NumberSerializer;
-import com.iailab.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
-import com.iailab.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.context.annotation.Bean;
-
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.util.List;
-
-@AutoConfiguration
-@Slf4j
-public class IailabJacksonAutoConfiguration {
-
-    @Bean
-    @SuppressWarnings("InstantiationOfUtilityClass")
-    public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
-        // 1.1 创建 SimpleModule 对象
-        SimpleModule simpleModule = new SimpleModule();
-        simpleModule
-                // 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
-                .addSerializer(Long.class, NumberSerializer.INSTANCE)
-                .addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
-                .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
-                .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
-                .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
-                .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
-                // 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
-                .addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
-                .addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
-        // 1.2 注册到 objectMapper
-        objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
-
-        // 2. 设置 objectMapper 到 JsonUtils
-        JsonUtils.init(CollUtil.getFirst(objectMappers));
-        log.info("[init][初始化 JsonUtils 成功]");
-        return new JsonUtils();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/NumberSerializer.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/NumberSerializer.java
deleted file mode 100644
index 53a6a75..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/NumberSerializer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.jackson.core.databind;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-
-import java.io.IOException;
-
-/**
- * Long 序列化规则
- *
- * 会将超长 long 值转换为 string,解决前端 JavaScript 最大安全整数是 2^53-1 的问题
- *
- * @author 星语
- */
-@JacksonStdImpl
-public class NumberSerializer extends com.fasterxml.jackson.databind.ser.std.NumberSerializer {
-
-    private static final long MAX_SAFE_INTEGER = 9007199254740991L;
-    private static final long MIN_SAFE_INTEGER = -9007199254740991L;
-
-    public static final NumberSerializer INSTANCE = new NumberSerializer(Number.class);
-
-    public NumberSerializer(Class<? extends Number> rawType) {
-        super(rawType);
-    }
-
-    @Override
-    public void serialize(Number value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
-        // 超出范围 序列化位字符串
-        if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
-            super.serialize(value, gen, serializers);
-        } else {
-            gen.writeString(value.toString());
-        }
-    }
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/TimestampLocalDateTimeDeserializer.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/TimestampLocalDateTimeDeserializer.java
deleted file mode 100644
index 4266193..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/TimestampLocalDateTimeDeserializer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.jackson.core.databind;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-
-/**
- * 基于时间戳的 LocalDateTime 反序列化器
- *
- * @author 老五
- */
-public class TimestampLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
-
-    public static final TimestampLocalDateTimeDeserializer INSTANCE = new TimestampLocalDateTimeDeserializer();
-
-    @Override
-    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
-        // 将 Long 时间戳,转换为 LocalDateTime 对象
-        return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/TimestampLocalDateTimeSerializer.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/TimestampLocalDateTimeSerializer.java
deleted file mode 100644
index f6485db..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/databind/TimestampLocalDateTimeSerializer.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.iailab.framework.jackson.core.databind;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-
-/**
- * 基于时间戳的 LocalDateTime 序列化器
- *
- * @author 老五
- */
-public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
-
-    public static final TimestampLocalDateTimeSerializer INSTANCE = new TimestampLocalDateTimeSerializer();
-
-    @Override
-    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
-        // 将 LocalDateTime 对象,转换为 Long 时间戳
-        gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/package-info.java
deleted file mode 100644
index 922937d..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/jackson/core/package-info.java
+++ /dev/null
@@ -1 +0,0 @@
-package com.iailab.framework.jackson.core;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/package-info.java
deleted file mode 100644
index 0deb23c..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Web 框架,全局异常、API 日志等
- */
-package com.iailab.framework;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java
deleted file mode 100644
index 331e7f0..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package com.iailab.framework.swagger.config;
-
-import io.swagger.v3.oas.models.Components;
-import io.swagger.v3.oas.models.OpenAPI;
-import io.swagger.v3.oas.models.info.Contact;
-import io.swagger.v3.oas.models.info.Info;
-import io.swagger.v3.oas.models.info.License;
-import io.swagger.v3.oas.models.media.IntegerSchema;
-import io.swagger.v3.oas.models.media.StringSchema;
-import io.swagger.v3.oas.models.parameters.Parameter;
-import io.swagger.v3.oas.models.security.SecurityRequirement;
-import io.swagger.v3.oas.models.security.SecurityScheme;
-import org.springdoc.core.*;
-import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
-import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
-import org.springdoc.core.providers.JavadocProvider;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Primary;
-import org.springframework.http.HttpHeaders;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
-
-/**
- * Swagger 自动配置类,基于 OpenAPI + Springdoc 实现。
- *
- * 友情提示:
- * 1. Springdoc 文档地址:<a href="https://github.com/springdoc/springdoc-openapi">仓库</a>
- * 2. Swagger 规范,于 2015 更名为 OpenAPI 规范,本质是一个东西
- *
- * @author iailab
- */
-@AutoConfiguration
-@ConditionalOnClass({OpenAPI.class})
-@EnableConfigurationProperties(SwaggerProperties.class)
-@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用
-public class IailabSwaggerAutoConfiguration {
-
-    // ========== 全局 OpenAPI 配置 ==========
-
-    @Bean
-    public OpenAPI createApi(SwaggerProperties properties) {
-        Map<String, SecurityScheme> securitySchemas = buildSecuritySchemes();
-        OpenAPI openAPI = new OpenAPI()
-                // 接口信息
-                .info(buildInfo(properties))
-                // 接口安全配置
-                .components(new Components().securitySchemes(securitySchemas))
-                .addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION));
-        securitySchemas.keySet().forEach(key -> openAPI.addSecurityItem(new SecurityRequirement().addList(key)));
-        return openAPI;
-    }
-
-    /**
-     * API 摘要信息
-     */
-    private Info buildInfo(SwaggerProperties properties) {
-        return new Info()
-                .title(properties.getTitle())
-                .description(properties.getDescription())
-                .version(properties.getVersion())
-                .contact(new Contact().name(properties.getAuthor()).url(properties.getUrl()).email(properties.getEmail()))
-                .license(new License().name(properties.getLicense()).url(properties.getLicenseUrl()));
-    }
-
-    /**
-     * 安全模式,这里配置通过请求头 Authorization 传递 token 参数
-     */
-    private Map<String, SecurityScheme> buildSecuritySchemes() {
-        Map<String, SecurityScheme> securitySchemes = new HashMap<>();
-        SecurityScheme securityScheme = new SecurityScheme()
-                .type(SecurityScheme.Type.APIKEY) // 类型
-                .name(HttpHeaders.AUTHORIZATION) // 请求头的 name
-                .in(SecurityScheme.In.HEADER); // token 所在位置
-        securitySchemes.put(HttpHeaders.AUTHORIZATION, securityScheme);
-        return securitySchemes;
-    }
-
-    /**
-     * 自定义 OpenAPI 处理器
-     */
-    @Bean
-    @Primary // 目的:以我们创建的 OpenAPIService Bean 为主,避免一键改包后,启动报错!
-    public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
-                                         SecurityService securityParser,
-                                         SpringDocConfigProperties springDocConfigProperties,
-                                         PropertyResolverUtils propertyResolverUtils,
-                                         Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
-                                         Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
-                                         Optional<JavadocProvider> javadocProvider) {
-
-        return new OpenAPIService(openAPI, securityParser, springDocConfigProperties,
-                propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);
-    }
-
-    // ========== 分组 OpenAPI 配置 ==========
-
-    /**
-     * 所有模块的 API 分组
-     */
-    @Bean
-    public GroupedOpenApi allGroupedOpenApi() {
-        return buildGroupedOpenApi("all", "");
-    }
-
-    public static GroupedOpenApi buildGroupedOpenApi(String group) {
-        return buildGroupedOpenApi(group, group);
-    }
-
-    public static GroupedOpenApi buildGroupedOpenApi(String group, String path) {
-        return GroupedOpenApi.builder()
-                .group(group)
-                .pathsToMatch("/admin-api/" + path + "/**", "/app-api/" + path + "/**")
-                .addOperationCustomizer((operation, handlerMethod) -> operation
-                        .addParametersItem(buildTenantHeaderParameter())
-                        .addParametersItem(buildSecurityHeaderParameter()))
-                .build();
-    }
-
-    /**
-     * 构建 Tenant 租户编号请求头参数
-     *
-     * @return 多租户参数
-     */
-    private static Parameter buildTenantHeaderParameter() {
-        return new Parameter()
-                .name(HEADER_TENANT_ID) // header 名
-                .description("租户编号") // 描述
-                .in(String.valueOf(SecurityScheme.In.HEADER)) // 请求 header
-                .schema(new IntegerSchema()._default(1L).name(HEADER_TENANT_ID).description("租户编号")); // 默认:使用租户编号为 1
-    }
-
-    /**
-     * 构建 Authorization 认证请求头参数
-     *
-     * 解决 Knife4j <a href="https://gitee.com/xiaoym/knife4j/issues/I69QBU">Authorize 未生效,请求header里未包含参数</a>
-     *
-     * @return 认证参数
-     */
-    private static Parameter buildSecurityHeaderParameter() {
-        return new Parameter()
-                .name(HttpHeaders.AUTHORIZATION) // header 名
-                .description("认证 Token") // 描述
-                .in(String.valueOf(SecurityScheme.In.HEADER)) // 请求 header
-                .schema(new StringSchema()._default("Bearer test1").name(HEADER_TENANT_ID).description("认证 Token")); // 默认:使用用户编号为 1
-    }
-
-}
-
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/SwaggerProperties.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/SwaggerProperties.java
deleted file mode 100644
index ab3bfeb..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/SwaggerProperties.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.framework.swagger.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-import javax.validation.constraints.NotEmpty;
-
-/**
- * Swagger 配置属性
- *
- * @author iailab
- */
-@ConfigurationProperties("iailab.swagger")
-@Data
-public class SwaggerProperties {
-
-    /**
-     * 标题
-     */
-    @NotEmpty(message = "标题不能为空")
-    private String title;
-    /**
-     * 描述
-     */
-    @NotEmpty(message = "描述不能为空")
-    private String description;
-    /**
-     * 作者
-     */
-    @NotEmpty(message = "作者不能为空")
-    private String author;
-    /**
-     * 版本
-     */
-    @NotEmpty(message = "版本不能为空")
-    private String version;
-    /**
-     * url
-     */
-    @NotEmpty(message = "扫描的 package 不能为空")
-    private String url;
-    /**
-     * email
-     */
-    @NotEmpty(message = "扫描的 email 不能为空")
-    private String email;
-
-    /**
-     * license
-     */
-    @NotEmpty(message = "扫描的 license 不能为空")
-    private String license;
-
-    /**
-     * license-url
-     */
-    @NotEmpty(message = "扫描的 license-url 不能为空")
-    private String licenseUrl;
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/package-info.java
deleted file mode 100644
index f30bbfb..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 基于 Swagger + Knife4j 实现 API 接口文档
- *
- * @author iailab
- */
-package com.iailab.framework.swagger;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/config/IailabWebAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/config/IailabWebAutoConfiguration.java
deleted file mode 100644
index 0a4b9cb..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/config/IailabWebAutoConfiguration.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.iailab.framework.web.config;
-
-import com.iailab.framework.apilog.core.service.ApiErrorLogFrameworkService;
-import com.iailab.framework.common.enums.WebFilterOrderEnum;
-import com.iailab.framework.web.core.filter.CacheRequestBodyFilter;
-import com.iailab.framework.web.core.filter.DemoFilter;
-import com.iailab.framework.web.core.handler.GlobalExceptionHandler;
-import com.iailab.framework.web.core.handler.GlobalResponseBodyHandler;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.util.AntPathMatcher;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-import org.springframework.web.filter.CorsFilter;
-import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-import javax.annotation.Resource;
-import javax.servlet.Filter;
-
-@AutoConfiguration
-@EnableConfigurationProperties(WebProperties.class)
-public class IailabWebAutoConfiguration implements WebMvcConfigurer {
-
-    @Resource
-    private WebProperties webProperties;
-    /**
-     * 应用名
-     */
-    @Value("${spring.application.name}")
-    private String applicationName;
-
-    @Override
-    public void configurePathMatch(PathMatchConfigurer configurer) {
-        configurePathMatch(configurer, webProperties.getAdminApi());
-        configurePathMatch(configurer, webProperties.getAppApi());
-    }
-
-    /**
-     * 设置 API 前缀,仅仅匹配 controller 包下的
-     *
-     * @param configurer 配置
-     * @param api        API 配置
-     */
-    private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) {
-        AntPathMatcher antPathMatcher = new AntPathMatcher(".");
-        configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class)
-                && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包
-    }
-
-    @Bean
-    public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogFrameworkService ApiErrorLogFrameworkService) {
-        return new GlobalExceptionHandler(applicationName, ApiErrorLogFrameworkService);
-    }
-
-    @Bean
-    public GlobalResponseBodyHandler globalResponseBodyHandler() {
-        return new GlobalResponseBodyHandler();
-    }
-
-    @Bean
-    @SuppressWarnings("InstantiationOfUtilityClass")
-    public WebFrameworkUtils webFrameworkUtils(WebProperties webProperties) {
-        // 由于 WebFrameworkUtils 需要使用到 webProperties 属性,所以注册为一个 Bean
-        return new WebFrameworkUtils(webProperties);
-    }
-
-    // ========== Filter 相关 ==========
-
-    /**
-     * 创建 CorsFilter Bean,解决跨域问题
-     */
-    @Bean
-    public FilterRegistrationBean<CorsFilter> corsFilterBean() {
-        // 创建 CorsConfiguration 对象
-        CorsConfiguration config = new CorsConfiguration();
-        config.setAllowCredentials(true);
-        config.addAllowedOriginPattern("*"); // 设置访问源地址
-        config.addAllowedHeader("*"); // 设置访问源请求头
-        config.addAllowedMethod("*"); // 设置访问源请求方法
-        // 创建 UrlBasedCorsConfigurationSource 对象
-        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-        source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置
-        return createFilterBean(new CorsFilter(source), WebFilterOrderEnum.CORS_FILTER);
-    }
-
-    /**
-     * 创建 RequestBodyCacheFilter Bean,可重复读取请求内容
-     */
-    @Bean
-    public FilterRegistrationBean<CacheRequestBodyFilter> requestBodyCacheFilter() {
-        return createFilterBean(new CacheRequestBodyFilter(), WebFilterOrderEnum.REQUEST_BODY_CACHE_FILTER);
-    }
-
-    /**
-     * 创建 DemoFilter Bean,演示模式
-     */
-    @Bean
-    @ConditionalOnProperty(value = "iailab.demo", havingValue = "true")
-    public FilterRegistrationBean<DemoFilter> demoFilter() {
-        return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER);
-    }
-
-    public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
-        FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
-        bean.setOrder(order);
-        return bean;
-    }
-
-    /**
-     * 创建 RestTemplate 实例
-     *
-     * @param restTemplateBuilder {@link RestTemplateAutoConfiguration#restTemplateBuilder}
-     */
-    @Bean
-    @ConditionalOnMissingBean
-    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
-        return restTemplateBuilder.build();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/config/WebProperties.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/config/WebProperties.java
deleted file mode 100644
index ecc5ab0..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/config/WebProperties.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.iailab.framework.web.config;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-@ConfigurationProperties(prefix = "iailab.web")
-@Validated
-@Data
-public class WebProperties {
-
-    @NotNull(message = "APP API 不能为空")
-    private Api appApi = new Api("/app-api", "**.controller.app.**");
-    @NotNull(message = "Admin API 不能为空")
-    private Api adminApi = new Api("/admin-api", "**.controller.admin.**");
-
-    @NotNull(message = "Admin UI 不能为空")
-    private Ui adminUi;
-
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    @Valid
-    public static class Api {
-
-        /**
-         * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀
-         *
-         *
-         * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题
-         *      这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。
-         *
-         * @see IailabWebAutoConfiguration#configurePathMatch(PathMatchConfigurer)
-         */
-        @NotEmpty(message = "API 前缀不能为空")
-        private String prefix;
-
-        /**
-         * Controller 所在包的 Ant 路径规则
-         *
-         * 主要目的是,给该 Controller 设置指定的 {@link #prefix}
-         */
-        @NotEmpty(message = "Controller 所在包不能为空")
-        private String controller;
-
-    }
-
-    @Data
-    @Valid
-    public static class Ui {
-
-        /**
-         * 访问地址
-         */
-        private String url;
-
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/ApiRequestFilter.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/ApiRequestFilter.java
deleted file mode 100644
index d3e4e46..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/ApiRequestFilter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.web.core.filter;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.web.config.WebProperties;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * 过滤 /admin-api、/app-api 等 API 请求的过滤器
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public abstract class ApiRequestFilter extends OncePerRequestFilter {
-
-    protected final WebProperties webProperties;
-
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) {
-        // 只过滤 API 请求的地址
-        return !StrUtil.startWithAny(request.getRequestURI(), webProperties.getAdminApi().getPrefix(),
-                webProperties.getAppApi().getPrefix());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/CacheRequestBodyFilter.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/CacheRequestBodyFilter.java
deleted file mode 100644
index 84a1e9a..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/CacheRequestBodyFilter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.iailab.framework.web.core.filter;
-
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * Request Body 缓存 Filter,实现它的可重复读取
- *
- * @author iailab
- */
-public class CacheRequestBodyFilter extends OncePerRequestFilter {
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-            throws IOException, ServletException {
-        filterChain.doFilter(new CacheRequestBodyWrapper(request), response);
-    }
-
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) {
-        // 只处理 json 请求内容
-        return !ServletUtils.isJsonRequest(request);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/CacheRequestBodyWrapper.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/CacheRequestBodyWrapper.java
deleted file mode 100644
index 18a5aa1..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/CacheRequestBodyWrapper.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.iailab.framework.web.core.filter;
-
-import com.iailab.framework.common.util.servlet.ServletUtils;
-
-import javax.servlet.ReadListener;
-import javax.servlet.ServletInputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-/**
- *  Request Body 缓存 Wrapper
- *
- * @author iailab
- */
-public class CacheRequestBodyWrapper extends HttpServletRequestWrapper {
-
-    /**
-     * 缓存的内容
-     */
-    private final byte[] body;
-
-    public CacheRequestBodyWrapper(HttpServletRequest request) {
-        super(request);
-        body = ServletUtils.getBodyBytes(request);
-    }
-
-    @Override
-    public BufferedReader getReader() throws IOException {
-        return new BufferedReader(new InputStreamReader(this.getInputStream()));
-    }
-
-    @Override
-    public ServletInputStream getInputStream() throws IOException {
-        final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
-        // 返回 ServletInputStream
-        return new ServletInputStream() {
-
-            @Override
-            public int read() {
-                return inputStream.read();
-            }
-
-            @Override
-            public boolean isFinished() {
-                return false;
-            }
-
-            @Override
-            public boolean isReady() {
-                return false;
-            }
-
-            @Override
-            public void setReadListener(ReadListener readListener) {}
-
-            @Override
-            public int available() {
-                return body.length;
-            }
-
-        };
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/DemoFilter.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/DemoFilter.java
deleted file mode 100644
index 43bd5cb..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/filter/DemoFilter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.web.core.filter;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY;
-
-/**
- * 演示 Filter,禁止用户发起写操作,避免影响测试数据
- *
- * @author iailab
- */
-public class DemoFilter extends OncePerRequestFilter {
-
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) {
-        String method = request.getMethod();
-        return !StrUtil.equalsAnyIgnoreCase(method, "POST", "PUT", "DELETE")  // 写操作时,不进行过滤率
-                || WebFrameworkUtils.getLoginUserId(request) == null; // 非登录用户时,不进行过滤
-    }
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
-        // 直接返回 DEMO_DENY 的结果。即,请求不继续
-        ServletUtils.writeJSON(response, CommonResult.error(DEMO_DENY));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalExceptionHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalExceptionHandler.java
deleted file mode 100644
index 79930b8..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalExceptionHandler.java
+++ /dev/null
@@ -1,356 +0,0 @@
-package com.iailab.framework.web.core.handler;
-
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.apilog.core.service.ApiErrorLogFrameworkService;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.collection.SetUtils;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.common.util.monitor.TracerUtils;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import com.iailab.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.util.Assert;
-import org.springframework.validation.BindException;
-import org.springframework.validation.FieldError;
-import org.springframework.web.HttpRequestMethodNotSupportedException;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.MissingServletRequestParameterException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
-import org.springframework.web.servlet.NoHandlerFoundException;
-import org.springframework.dao.DuplicateKeyException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.validation.ConstraintViolation;
-import javax.validation.ConstraintViolationException;
-import javax.validation.ValidationException;
-import java.time.LocalDateTime;
-import java.util.Map;
-import java.util.Set;
-
-import static com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants.*;
-
-/**
- * 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号
- *
- * @author iailab
- */
-@RestControllerAdvice
-@AllArgsConstructor
-@Slf4j
-public class GlobalExceptionHandler {
-
-    /**
-     * 忽略的 ServiceException 错误提示,避免打印过多 logger
-     */
-    public static final Set<String> IGNORE_ERROR_MESSAGES = SetUtils.asSet("无效的刷新令牌");
-
-    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
-    private final String applicationName;
-
-    private final ApiErrorLogFrameworkService apiErrorLogFrameworkService;
-
-    /**
-     * 处理所有异常,主要是提供给 Filter 使用
-     * 因为 Filter 不走 SpringMVC 的流程,但是我们又需要兜底处理异常,所以这里提供一个全量的异常处理过程,保持逻辑统一。
-     *
-     * @param request 请求
-     * @param ex 异常
-     * @return 通用返回
-     */
-    public CommonResult<?> allExceptionHandler(HttpServletRequest request, Throwable ex) {
-        if (ex instanceof MissingServletRequestParameterException) {
-            return missingServletRequestParameterExceptionHandler((MissingServletRequestParameterException) ex);
-        }
-        if (ex instanceof MethodArgumentTypeMismatchException) {
-            return methodArgumentTypeMismatchExceptionHandler((MethodArgumentTypeMismatchException) ex);
-        }
-        if (ex instanceof MethodArgumentNotValidException) {
-            return methodArgumentNotValidExceptionExceptionHandler((MethodArgumentNotValidException) ex);
-        }
-        if (ex instanceof BindException) {
-            return bindExceptionHandler((BindException) ex);
-        }
-        if (ex instanceof ConstraintViolationException) {
-            return constraintViolationExceptionHandler((ConstraintViolationException) ex);
-        }
-        if (ex instanceof ValidationException) {
-            return validationException((ValidationException) ex);
-        }
-        if (ex instanceof NoHandlerFoundException) {
-            return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex);
-        }
-        if (ex instanceof HttpRequestMethodNotSupportedException) {
-            return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
-        }
-        if (ex instanceof ServiceException) {
-            return serviceExceptionHandler((ServiceException) ex);
-        }
-        if (ex instanceof AccessDeniedException) {
-            return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
-        }
-        if (ex instanceof DuplicateKeyException) {
-            return duplicateKeyExceptionHandler((DuplicateKeyException) ex);
-        }
-        return defaultExceptionHandler(request, ex);
-    }
-
-    /**
-     * 处理 SpringMVC 请求参数缺失
-     *
-     * 例如说,接口上设置了 @RequestParam("xx") 参数,结果并未传递 xx 参数
-     */
-    @ExceptionHandler(value = MissingServletRequestParameterException.class)
-    public CommonResult<?> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex) {
-        log.warn("[missingServletRequestParameterExceptionHandler]", ex);
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s", ex.getParameterName()));
-    }
-
-    /**
-     * 处理 SpringMVC 请求参数类型错误
-     *
-     * 例如说,接口上设置了 @RequestParam("xx") 参数为 Integer,结果传递 xx 参数类型为 String
-     */
-    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
-    public CommonResult<?> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) {
-        log.warn("[missingServletRequestParameterExceptionHandler]", ex);
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage()));
-    }
-
-    /**
-     * 处理 SpringMVC 参数校验不正确
-     */
-    @ExceptionHandler(MethodArgumentNotValidException.class)
-    public CommonResult<?> methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) {
-        log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex);
-        FieldError fieldError = ex.getBindingResult().getFieldError();
-        assert fieldError != null; // 断言,避免告警
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
-    }
-
-    /**
-     * 处理 SpringMVC 参数绑定不正确,本质上也是通过 Validator 校验
-     */
-    @ExceptionHandler(BindException.class)
-    public CommonResult<?> bindExceptionHandler(BindException ex) {
-        log.warn("[handleBindException]", ex);
-        FieldError fieldError = ex.getFieldError();
-        assert fieldError != null; // 断言,避免告警
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
-    }
-
-    /**
-     * 处理 Validator 校验不通过产生的异常
-     */
-    @ExceptionHandler(value = ConstraintViolationException.class)
-    public CommonResult<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
-        log.warn("[constraintViolationExceptionHandler]", ex);
-        ConstraintViolation<?> constraintViolation = ex.getConstraintViolations().iterator().next();
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", constraintViolation.getMessage()));
-    }
-
-    /**
-     * 处理 Dubbo Consumer 本地参数校验时,抛出的 ValidationException 异常
-     */
-    @ExceptionHandler(value = ValidationException.class)
-    public CommonResult<?> validationException(ValidationException ex) {
-        log.warn("[constraintViolationExceptionHandler]", ex);
-        // 无法拼接明细的错误信息,因为 Dubbo Consumer 抛出 ValidationException 异常时,是直接的字符串信息,且人类不可读
-        return CommonResult.error(BAD_REQUEST);
-    }
-
-    /**
-     * 处理 SpringMVC 请求地址不存在
-     *
-     * 注意,它需要设置如下两个配置项:
-     * 1. spring.mvc.throw-exception-if-no-handler-found 为 true
-     * 2. spring.mvc.static-path-pattern 为 /statics/**
-     */
-    @ExceptionHandler(NoHandlerFoundException.class)
-    public CommonResult<?> noHandlerFoundExceptionHandler(NoHandlerFoundException ex) {
-        log.warn("[noHandlerFoundExceptionHandler]", ex);
-        return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
-    }
-
-    /**
-     * 处理 SpringMVC 请求方法不正确
-     *
-     * 例如说,A 接口的方法为 GET 方式,结果请求方法为 POST 方式,导致不匹配
-     */
-    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
-    public CommonResult<?> httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) {
-        log.warn("[httpRequestMethodNotSupportedExceptionHandler]", ex);
-        return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
-    }
-
-    /**
-     * 处理 Spring Security 权限不足的异常
-     *
-     * 来源是,使用 @PreAuthorize 注解,AOP 进行权限拦截
-     */
-    @ExceptionHandler(value = AccessDeniedException.class)
-    public CommonResult<?> accessDeniedExceptionHandler(HttpServletRequest req, AccessDeniedException ex) {
-        log.warn("[accessDeniedExceptionHandler][userId({}) 无法访问 url({})]", WebFrameworkUtils.getLoginUserId(req),
-                req.getRequestURL(), ex);
-        return CommonResult.error(FORBIDDEN);
-    }
-
-    /**
-     * 处理业务异常 SQLIntegrityConstraintViolationException
-     *
-     * 数据库存在重复数据
-     */
-    @ExceptionHandler(value = DuplicateKeyException.class)
-    public CommonResult<?> duplicateKeyExceptionHandler(DuplicateKeyException ex) {
-        log.warn("[duplicateKeyExceptionHandler]", ex);
-        return CommonResult.error(DATA_REPETITION.getCode(), DATA_REPETITION.getMsg());
-    }
-
-    /**
-     * 处理业务异常 ServiceException
-     *
-     * 例如说,商品库存不足,用户手机号已存在。
-     */
-    @ExceptionHandler(value = ServiceException.class)
-    public CommonResult<?> serviceExceptionHandler(ServiceException ex) {
-        // 不包含的时候,才进行打印,避免 ex 堆栈过多
-        if (!IGNORE_ERROR_MESSAGES.contains(ex.getMessage())) {
-            // 即使打印,也只打印第一层 StackTraceElement,并且使用 warn 在控制台输出,更容易看到
-            StackTraceElement[] stackTrace = ex.getStackTrace();
-            log.warn("[serviceExceptionHandler]\n\t{}", stackTrace[0]);
-        }
-        return CommonResult.error(ex.getCode(), ex.getMessage());
-    }
-
-    /**
-     * 处理系统异常,兜底处理所有的一切
-     */
-    @ExceptionHandler(value = Exception.class)
-    public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
-        // 情况一:处理表不存在的异常
-        CommonResult<?> tableNotExistsResult = handleTableNotExists(ex);
-        if (tableNotExistsResult != null) {
-            return tableNotExistsResult;
-        }
-
-        // 情况二:处理异常
-        log.error("[defaultExceptionHandler]", ex);
-        // 插入异常日志
-        createExceptionLog(req, ex);
-        // 返回 ERROR CommonResult
-        return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
-    }
-
-    private void createExceptionLog(HttpServletRequest req, Throwable e) {
-        // 插入错误日志
-        ApiErrorLogCreateReqDTO errorLog = new ApiErrorLogCreateReqDTO();
-        try {
-            // 初始化 errorLog
-            buildExceptionLog(errorLog, req, e);
-            // 执行插入 errorLog
-            apiErrorLogFrameworkService.createApiErrorLog(errorLog);
-        } catch (Throwable th) {
-            log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(),  JsonUtils.toJsonString(errorLog), th);
-        }
-    }
-
-    private void buildExceptionLog(ApiErrorLogCreateReqDTO errorLog, HttpServletRequest request, Throwable e) {
-        // 处理用户信息
-        errorLog.setUserId(WebFrameworkUtils.getLoginUserId(request));
-        errorLog.setUserType(WebFrameworkUtils.getLoginUserType(request));
-        // 设置异常字段
-        errorLog.setExceptionName(e.getClass().getName());
-        errorLog.setExceptionMessage(ExceptionUtil.getMessage(e));
-        errorLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e));
-        errorLog.setExceptionStackTrace(ExceptionUtil.stacktraceToString(e));
-        StackTraceElement[] stackTraceElements = e.getStackTrace();
-        Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空");
-        StackTraceElement stackTraceElement = stackTraceElements[0];
-        errorLog.setExceptionClassName(stackTraceElement.getClassName());
-        errorLog.setExceptionFileName(stackTraceElement.getFileName());
-        errorLog.setExceptionMethodName(stackTraceElement.getMethodName());
-        errorLog.setExceptionLineNumber(stackTraceElement.getLineNumber());
-        // 设置其它字段
-        errorLog.setTraceId(TracerUtils.getTraceId());
-        errorLog.setApplicationName(applicationName);
-        errorLog.setRequestUrl(request.getRequestURI());
-        Map<String, Object> requestParams = MapUtil.<String, Object>builder()
-                .put("query", ServletUtils.getParamMap(request))
-                .put("body", ServletUtils.getBody(request)).build();
-        errorLog.setRequestParams(JsonUtils.toJsonString(requestParams));
-        errorLog.setRequestMethod(request.getMethod());
-        errorLog.setUserAgent(ServletUtils.getUserAgent(request));
-        errorLog.setUserIp(ServletUtils.getClientIP(request));
-        errorLog.setExceptionTime(LocalDateTime.now());
-    }
-
-    /**
-     * 处理 Table 不存在的异常情况
-     *
-     * @param ex 异常
-     * @return 如果是 Table 不存在的异常,则返回对应的 CommonResult
-     */
-    private CommonResult<?> handleTableNotExists(Throwable ex) {
-        String message = ExceptionUtil.getRootCauseMessage(ex);
-        if (!message.contains("doesn't exist")) {
-            return null;
-        }
-        // 1. 数据报表
-        if (message.contains("report_")) {
-            log.error("[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[报表模块 yudao-module-report - 表结构未导入][参考 https://cloud.iocoder.cn/report/ 开启]");
-        }
-        // 2. 工作流
-        if (message.contains("bpm_")) {
-            log.error("[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[工作流模块 yudao-module-bpm - 表结构未导入][参考 https://cloud.iocoder.cn/bpm/ 开启]");
-        }
-        // 3. 微信公众号
-        if (message.contains("mp_")) {
-            log.error("[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[微信公众号 yudao-module-mp - 表结构未导入][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
-        }
-        // 4. 商城系统
-        if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) {
-            log.error("[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[商城系统 yudao-module-mall - 已禁用][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
-        }
-        // 5. ERP 系统
-        if (message.contains("erp_")) {
-            log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
-        }
-        // 6. CRM 系统
-        if (message.contains("crm_")) {
-            log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
-        }
-        // 7. 支付平台
-        if (message.contains("pay_")) {
-            log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
-        }
-        // 8. AI 大模型
-        if (message.contains("ai_")) {
-            log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
-            return CommonResult.error(NOT_IMPLEMENTED.getCode(),
-                    "[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
-        }
-        return null;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalResponseBodyHandler.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalResponseBodyHandler.java
deleted file mode 100644
index 36b3aca..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/handler/GlobalResponseBodyHandler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.iailab.framework.web.core.handler;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.web.core.util.WebFrameworkUtils;
-import org.springframework.core.MethodParameter;
-import org.springframework.http.MediaType;
-import org.springframework.http.server.ServerHttpRequest;
-import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.http.server.ServletServerHttpRequest;
-import org.springframework.web.bind.annotation.ControllerAdvice;
-import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
-
-/**
- * 全局响应结果(ResponseBody)处理器
- *
- * 不同于在网上看到的很多文章,会选择自动将 Controller 返回结果包上 {@link CommonResult},
- * 在 onemall 中,是 Controller 在返回时,主动自己包上 {@link CommonResult}。
- * 原因是,GlobalResponseBodyHandler 本质上是 AOP,它不应该改变 Controller 返回的数据结构
- *
- * 目前,GlobalResponseBodyHandler 的主要作用是,记录 Controller 的返回结果,
- * 方便 {@link com.iailab.framework.apilog.core.filter.ApiAccessLogFilter} 记录访问日志
- */
-@ControllerAdvice
-public class GlobalResponseBodyHandler implements ResponseBodyAdvice {
-
-    @Override
-    @SuppressWarnings("NullableProblems") // 避免 IDEA 警告
-    public boolean supports(MethodParameter returnType, Class converterType) {
-        if (returnType.getMethod() == null) {
-            return false;
-        }
-        // 只拦截返回结果为 CommonResult 类型
-        return returnType.getMethod().getReturnType() == CommonResult.class;
-    }
-
-    @Override
-    @SuppressWarnings("NullableProblems") // 避免 IDEA 警告
-    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
-                                  ServerHttpRequest request, ServerHttpResponse response) {
-        // 记录 Controller 结果
-        WebFrameworkUtils.setCommonResult(((ServletServerHttpRequest) request).getServletRequest(), (CommonResult<?>) body);
-        return body;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/util/WebFrameworkUtils.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/util/WebFrameworkUtils.java
deleted file mode 100644
index 08cc572..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/core/util/WebFrameworkUtils.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package com.iailab.framework.web.core.util;
-
-import cn.hutool.core.util.NumberUtil;
-import cn.hutool.extra.servlet.ServletUtil;
-import com.iailab.framework.common.enums.RpcConstants;
-import com.iailab.framework.common.enums.TerminalEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.web.config.WebProperties;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * 专属于 web 包的工具类
- *
- * @author iailab
- */
-public class WebFrameworkUtils {
-
-    private static final String REQUEST_ATTRIBUTE_LOGIN_USER_ID = "login_user_id";
-    private static final String REQUEST_ATTRIBUTE_LOGIN_USER_TYPE = "login_user_type";
-
-    private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result";
-
-    public static final String HEADER_TENANT_ID = "tenant-id";
-
-    /**
-     * 终端的 Header
-     *
-     * @see com.iailab.framework.common.enums.TerminalEnum
-     */
-    public static final String HEADER_TERMINAL = "terminal";
-
-    private static WebProperties properties;
-
-    public WebFrameworkUtils(WebProperties webProperties) {
-        WebFrameworkUtils.properties = webProperties;
-    }
-
-    /**
-     * 获得租户编号,从 header 中
-     * 考虑到其它 framework 组件也会使用到租户编号,所以不得不放在 WebFrameworkUtils 统一提供
-     *
-     * @param request 请求
-     * @return 租户编号
-     */
-    public static Long getTenantId(HttpServletRequest request) {
-        String tenantId = request.getHeader(HEADER_TENANT_ID);
-        return NumberUtil.isNumber(tenantId) ? Long.valueOf(tenantId) : null;
-    }
-
-    public static void setLoginUserId(ServletRequest request, Long userId) {
-        request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID, userId);
-    }
-
-    /**
-     * 设置用户类型
-     *
-     * @param request 请求
-     * @param userType 用户类型
-     */
-    public static void setLoginUserType(ServletRequest request, Integer userType) {
-        request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_TYPE, userType);
-    }
-
-    /**
-     * 获得当前用户的编号,从请求中
-     * 注意:该方法仅限于 framework 框架使用!!!
-     *
-     * @param request 请求
-     * @return 用户编号
-     */
-    public static Long getLoginUserId(HttpServletRequest request) {
-        if (request == null) {
-            return null;
-        }
-        return (Long) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID);
-    }
-
-    /**
-     * 获得当前用户的类型
-     * 注意:该方法仅限于 web 相关的 framework 组件使用!!!
-     *
-     * @param request 请求
-     * @return 用户编号
-     */
-    public static Integer getLoginUserType(HttpServletRequest request) {
-        if (request == null) {
-            return null;
-        }
-        // 1. 优先,从 Attribute 中获取
-        Integer userType = (Integer) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_TYPE);
-        if (userType != null) {
-            return userType;
-        }
-        // 2. 其次,基于 URL 前缀的约定
-        if (request.getServletPath().startsWith(properties.getAdminApi().getPrefix())) {
-            return UserTypeEnum.ADMIN.getValue();
-        }
-        if (request.getServletPath().startsWith(properties.getAppApi().getPrefix())) {
-            return UserTypeEnum.MEMBER.getValue();
-        }
-        return null;
-    }
-
-    public static Integer getLoginUserType() {
-        HttpServletRequest request = getRequest();
-        return getLoginUserType(request);
-    }
-
-    public static Long getLoginUserId() {
-        HttpServletRequest request = getRequest();
-        return getLoginUserId(request);
-    }
-
-    public static Integer getTerminal() {
-        HttpServletRequest request = getRequest();
-        if (request == null) {
-            return TerminalEnum.UNKNOWN.getTerminal();
-        }
-        String terminalValue = request.getHeader(HEADER_TERMINAL);
-        return NumberUtil.parseInt(terminalValue, TerminalEnum.UNKNOWN.getTerminal());
-    }
-
-    public static void setCommonResult(ServletRequest request, CommonResult<?> result) {
-        request.setAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT, result);
-    }
-
-    public static CommonResult<?> getCommonResult(ServletRequest request) {
-        return (CommonResult<?>) request.getAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT);
-    }
-
-    public static HttpServletRequest getRequest() {
-        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
-        if (!(requestAttributes instanceof ServletRequestAttributes)) {
-            return null;
-        }
-        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
-        return servletRequestAttributes.getRequest();
-    }
-
-    /**
-     * 判断是否为 RPC 请求
-     *
-     * @param request 请求
-     * @return 是否为 RPC 请求
-     */
-    public static boolean isRpcRequest(HttpServletRequest request) {
-        return request.getRequestURI().startsWith(RpcConstants.RPC_API_PREFIX);
-    }
-
-    /**
-     * 判断是否为 RPC 请求
-     *
-     * 约定大于配置,只要以 Api 结尾,都认为是 RPC 接口
-     *
-     * @param className 类名
-     * @return 是否为 RPC 请求
-     */
-    public static boolean isRpcRequest(String className) {
-        return className.endsWith("Api");
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/package-info.java
deleted file mode 100644
index 53e1115..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/web/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 针对 SpringMVC 的基础封装
- */
-package com.iailab.framework.web;
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/config/IailabXssAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/config/IailabXssAutoConfiguration.java
deleted file mode 100644
index ed97017..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/config/IailabXssAutoConfiguration.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.iailab.framework.xss.config;
-
-import com.iailab.framework.common.enums.WebFilterOrderEnum;
-import com.iailab.framework.xss.core.clean.JsoupXssCleaner;
-import com.iailab.framework.xss.core.clean.XssCleaner;
-import com.iailab.framework.xss.core.filter.XssFilter;
-import com.iailab.framework.xss.core.json.XssStringJsonDeserializer;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.util.PathMatcher;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-import static com.iailab.framework.web.config.IailabWebAutoConfiguration.createFilterBean;
-
-@AutoConfiguration
-@EnableConfigurationProperties(XssProperties.class)
-@ConditionalOnProperty(prefix = "iailab.xss", name = "enable", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用
-public class IailabXssAutoConfiguration implements WebMvcConfigurer {
-
-    /**
-     * Xss 清理者
-     *
-     * @return XssCleaner
-     */
-    @Bean
-    @ConditionalOnMissingBean(XssCleaner.class)
-    public XssCleaner xssCleaner() {
-        return new JsoupXssCleaner();
-    }
-
-    /**
-     * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤
-     *
-     * @return Jackson2ObjectMapperBuilderCustomizer
-     */
-    @Bean
-    @ConditionalOnMissingBean(name = "xssJacksonCustomizer")
-    @ConditionalOnBean(ObjectMapper.class)
-    @ConditionalOnProperty(value = "iailab.xss.enable", havingValue = "true")
-    public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssProperties properties,
-                                                                      PathMatcher pathMatcher,
-                                                                      XssCleaner xssCleaner) {
-        // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理
-        return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(properties, pathMatcher, xssCleaner));
-    }
-
-    /**
-     * 创建 XssFilter Bean,解决 Xss 安全问题
-     */
-    @Bean
-    @ConditionalOnBean(XssCleaner.class)
-    public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) {
-        return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/config/XssProperties.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/config/XssProperties.java
deleted file mode 100644
index 1c4d970..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/config/XssProperties.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.iailab.framework.xss.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Xss 配置属性
- *
- * @author iailab
- */
-@ConfigurationProperties(prefix = "iailab.xss")
-@Validated
-@Data
-public class XssProperties {
-
-    /**
-     * 是否开启,默认为 true
-     */
-    private boolean enable = true;
-    /**
-     * 需要排除的 URL,默认为空
-     */
-    private List<String> excludeUrls = Collections.emptyList();
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/clean/JsoupXssCleaner.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/clean/JsoupXssCleaner.java
deleted file mode 100644
index 4636994..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/clean/JsoupXssCleaner.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.iailab.framework.xss.core.clean;
-
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.safety.Safelist;
-
-/**
- * 基于 JSONP 实现 XSS 过滤字符串
- */
-public class JsoupXssCleaner implements XssCleaner {
-
-    private final Safelist safelist;
-
-    /**
-     * 用于在 src 属性使用相对路径时,强制转换为绝对路径。 为空时不处理,值应为绝对路径的前缀(包含协议部分)
-     */
-    private final String baseUri;
-
-    /**
-     * 无参构造,默认使用 {@link JsoupXssCleaner#buildSafelist} 方法构建一个安全列表
-     */
-    public JsoupXssCleaner() {
-        this.safelist = buildSafelist();
-        this.baseUri = "";
-    }
-
-    /**
-     * 构建一个 Xss 清理的 Safelist 规则。
-     * 基于 Safelist#relaxed() 的基础上:
-     * 1. 扩展支持了 style 和 class 属性
-     * 2. a 标签额外支持了 target 属性
-     * 3. img 标签额外支持了 data 协议,便于支持 base64
-     *
-     * @return Safelist
-     */
-    private Safelist buildSafelist() {
-        // 使用 jsoup 提供的默认的
-        Safelist relaxedSafelist = Safelist.relaxed();
-        // 富文本编辑时一些样式是使用 style 来进行实现的
-        // 比如红色字体 style="color:red;", 所以需要给所有标签添加 style 属性
-        // 注意:style 属性会有注入风险 <img STYLE="background-image:url(javascript:alert('XSS'))">
-        relaxedSafelist.addAttributes(":all", "style", "class");
-        // 保留 a 标签的 target 属性
-        relaxedSafelist.addAttributes("a", "target");
-        // 支持img 为base64
-        relaxedSafelist.addProtocols("img", "src", "data");
-
-        // 保留相对路径, 保留相对路径时,必须提供对应的 baseUri 属性,否则依然会被删除
-        // WHITELIST.preserveRelativeLinks(false);
-
-        // 移除 a 标签和 img 标签的一些协议限制,这会导致 xss 防注入失效,如 <img src=javascript:alert("xss")>
-        // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径
-        // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto");
-        // WHITELIST.removeProtocols("img", "src", "http", "https");
-        return relaxedSafelist;
-    }
-
-    @Override
-    public String clean(String html) {
-        return Jsoup.clean(html, baseUri, safelist, new Document.OutputSettings().prettyPrint(false));
-    }
-
-}
-
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/clean/XssCleaner.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/clean/XssCleaner.java
deleted file mode 100644
index d15b77e..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/clean/XssCleaner.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.iailab.framework.xss.core.clean;
-
-/**
- * 对 html 文本中的有 Xss 风险的数据进行清理
- */
-public interface XssCleaner {
-
-    /**
-     * 清理有 Xss 风险的文本
-     *
-     * @param html 原 html
-     * @return 清理后的 html
-     */
-    String clean(String html);
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/filter/XssFilter.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/filter/XssFilter.java
deleted file mode 100644
index 59c9347..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/filter/XssFilter.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.iailab.framework.xss.core.filter;
-
-import com.iailab.framework.xss.config.XssProperties;
-import com.iailab.framework.xss.core.clean.XssCleaner;
-import lombok.AllArgsConstructor;
-import org.springframework.util.PathMatcher;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * Xss 过滤器
- *
- * @author iailab
- */
-@AllArgsConstructor
-public class XssFilter extends OncePerRequestFilter {
-
-    /**
-     * 属性
-     */
-    private final XssProperties properties;
-    /**
-     * 路径匹配器
-     */
-    private final PathMatcher pathMatcher;
-
-    private final XssCleaner xssCleaner;
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-            throws IOException, ServletException {
-        filterChain.doFilter(new XssRequestWrapper(request, xssCleaner), response);
-    }
-
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) {
-        // 如果关闭,则不过滤
-        if (!properties.isEnable()) {
-            return true;
-        }
-
-        // 如果匹配到无需过滤,则不过滤
-        String uri = request.getRequestURI();
-        return properties.getExcludeUrls().stream().anyMatch(excludeUrl -> pathMatcher.match(excludeUrl, uri));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/filter/XssRequestWrapper.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/filter/XssRequestWrapper.java
deleted file mode 100644
index 04acb35..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/filter/XssRequestWrapper.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.iailab.framework.xss.core.filter;
-
-import com.iailab.framework.xss.core.clean.XssCleaner;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * Xss 请求 Wrapper
- *
- * @author iailab
- */
-public class XssRequestWrapper extends HttpServletRequestWrapper {
-
-    private final XssCleaner xssCleaner;
-
-    public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) {
-        super(request);
-        this.xssCleaner = xssCleaner;
-    }
-
-    // ============================ parameter ============================
-    @Override
-    public Map<String, String[]> getParameterMap() {
-        Map<String, String[]> map = new LinkedHashMap<>();
-        Map<String, String[]> parameters = super.getParameterMap();
-        for (Map.Entry<String, String[]> entry : parameters.entrySet()) {
-            String[] values = entry.getValue();
-            for (int i = 0; i < values.length; i++) {
-                values[i] = xssCleaner.clean(values[i]);
-            }
-            map.put(entry.getKey(), values);
-        }
-        return map;
-    }
-
-    @Override
-    public String[] getParameterValues(String name) {
-        String[] values = super.getParameterValues(name);
-        if (values == null) {
-            return null;
-        }
-        int count = values.length;
-        String[] encodedValues = new String[count];
-        for (int i = 0; i < count; i++) {
-            encodedValues[i] = xssCleaner.clean(values[i]);
-        }
-        return encodedValues;
-    }
-
-    @Override
-    public String getParameter(String name) {
-        String value = super.getParameter(name);
-        if (value == null) {
-            return null;
-        }
-        return xssCleaner.clean(value);
-    }
-
-    // ============================ attribute ============================
-    @Override
-    public Object getAttribute(String name) {
-        Object value = super.getAttribute(name);
-        if (value instanceof String) {
-            return xssCleaner.clean((String) value);
-        }
-        return value;
-    }
-
-    // ============================ header ============================
-    @Override
-    public String getHeader(String name) {
-        String value = super.getHeader(name);
-        if (value == null) {
-            return null;
-        }
-        return xssCleaner.clean(value);
-    }
-
-    // ============================ queryString ============================
-    @Override
-    public String getQueryString() {
-        String value = super.getQueryString();
-        if (value == null) {
-            return null;
-        }
-        return xssCleaner.clean(value);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/json/XssStringJsonDeserializer.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/json/XssStringJsonDeserializer.java
deleted file mode 100644
index 83f6f94..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/core/json/XssStringJsonDeserializer.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.iailab.framework.xss.core.json;
-
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.framework.xss.config.XssProperties;
-import com.iailab.framework.xss.core.clean.XssCleaner;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.PathMatcher;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-
-/**
- * XSS 过滤 jackson 反序列化器。
- * 在反序列化的过程中,会对字符串进行 XSS 过滤。
- *
- * @author Hccake
- */
-@Slf4j
-@AllArgsConstructor
-public class XssStringJsonDeserializer extends StringDeserializer {
-
-    /**
-     * 属性
-     */
-    private final XssProperties properties;
-    /**
-     * 路径匹配器
-     */
-    private final PathMatcher pathMatcher;
-
-    private final XssCleaner xssCleaner;
-
-    @Override
-    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
-        // 1. 白名单 URL 的处理
-        HttpServletRequest request = ServletUtils.getRequest();
-        if (request != null) {
-            String uri = ServletUtils.getRequest().getRequestURI();
-            if (properties.getExcludeUrls().stream().anyMatch(excludeUrl -> pathMatcher.match(excludeUrl, uri))) {
-                return p.getText();
-            }
-        }
-
-        // 2. 真正使用 xssCleaner 进行过滤
-        if (p.hasToken(JsonToken.VALUE_STRING)) {
-            return xssCleaner.clean(p.getText());
-        }
-        JsonToken t = p.currentToken();
-        // [databind#381]
-        if (t == JsonToken.START_ARRAY) {
-            return _deserializeFromArray(p, ctxt);
-        }
-        // need to gracefully handle byte[] data, as base64
-        if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
-            Object ob = p.getEmbeddedObject();
-            if (ob == null) {
-                return null;
-            }
-            if (ob instanceof byte[]) {
-                return ctxt.getBase64Variant().encode((byte[]) ob, false);
-            }
-            // otherwise, try conversion using toString()...
-            return ob.toString();
-        }
-        // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
-        if (t == JsonToken.START_OBJECT) {
-            return ctxt.extractScalarFromObject(p, this, _valueClass);
-        }
-
-        if (t.isScalarValue()) {
-            String text = p.getValueAsString();
-            return xssCleaner.clean(text);
-        }
-        return (String) ctxt.handleUnexpectedToken(_valueClass, p);
-    }
-}
-
diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/package-info.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/package-info.java
deleted file mode 100644
index 8e6ce67..0000000
--- a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/xss/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 针对 XSS 的基础封装
- *
- * XSS 说明:https://tech.meituan.com/2018/09/27/fe-security.html
- */
-package com.iailab.framework.xss;
diff --git a/iailab-framework/iailab-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index e7ad084..0000000
--- a/iailab-framework/iailab-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,6 +0,0 @@
-com.iailab.framework.apilog.config.IailabApiLogAutoConfiguration
-com.iailab.framework.jackson.config.IailabJacksonAutoConfiguration
-com.iailab.framework.swagger.config.IailabSwaggerAutoConfiguration
-com.iailab.framework.web.config.IailabWebAutoConfiguration
-com.iailab.framework.apilog.config.IailabApiLogRpcAutoConfiguration
-com.iailab.framework.banner.config.IailabBannerAutoConfiguration
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-web/src/main/resources/banner.txt b/iailab-framework/iailab-common-web/src/main/resources/banner.txt
deleted file mode 100644
index 65b7f42..0000000
--- a/iailab-framework/iailab-common-web/src/main/resources/banner.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-iailab
-Application Version: ${iailab.info.version}
-Spring Boot Version: ${spring-boot.version}
-
- ██           ██  ██           ██                 ██             ██     ████
-░░           ░░  ░██          ░██        ██████  ░██            ░██    ░██░
- ██  ██████   ██ ░██  ██████  ░██       ░██░░░██ ░██  ██████   ██████ ██████  ██████  ██████ ██████████
-░██ ░░░░░░██ ░██ ░██ ░░░░░░██ ░██████   ░██  ░██ ░██ ░░░░░░██ ░░░██░ ░░░██░  ██░░░░██░░██░░█░░██░░██░░██
-░██  ███████ ░██ ░██  ███████ ░██░░░██  ░██████  ░██  ███████   ░██    ░██  ░██   ░██ ░██ ░  ░██ ░██ ░██
-░██ ██░░░░██ ░██ ░██ ██░░░░██ ░██  ░██  ░██░░░   ░██ ██░░░░██   ░██    ░██  ░██   ░██ ░██    ░██ ░██ ░██
-░██░░████████░██ ███░░████████░██████   ░██      ███░░████████  ░░██   ░██  ░░██████ ░███    ███ ░██ ░██
-░░  ░░░░░░░░ ░░ ░░░  ░░░░░░░░ ░░░░░     ░░      ░░░  ░░░░░░░░    ░░    ░░    ░░░░░░  ░░░    ░░░  ░░  ░░
diff --git a/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/DesensitizeTest.java b/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/DesensitizeTest.java
deleted file mode 100644
index bb7a62a..0000000
--- a/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/DesensitizeTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.iailab.framework.desensitize.core;
-
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.desensitize.core.regex.annotation.EmailDesensitize;
-import com.iailab.framework.desensitize.core.regex.annotation.RegexDesensitize;
-import com.iailab.framework.desensitize.core.annotation.Address;
-import com.iailab.framework.desensitize.core.slider.annotation.BankCardDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.CarLicenseDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.ChineseNameDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.IdCardDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.PasswordDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.MobileDesensitize;
-import com.iailab.framework.desensitize.core.slider.annotation.SliderDesensitize;
-import lombok.Data;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link DesensitizeTest} 的单元测试
- */
-@ExtendWith(MockitoExtension.class)
-public class DesensitizeTest {
-
-    @Test
-    public void test() {
-        // 准备参数
-        DesensitizeDemo desensitizeDemo = new DesensitizeDemo();
-        desensitizeDemo.setNickname("iailab");
-        desensitizeDemo.setBankCard("9988002866797031");
-        desensitizeDemo.setCarLicense("粤A66666");
-        desensitizeDemo.setFixedPhone("01086551122");
-        desensitizeDemo.setIdCard("530321199204074611");
-        desensitizeDemo.setPassword("123456");
-        desensitizeDemo.setPhoneNumber("13248765917");
-        desensitizeDemo.setSlider1("ABCDEFG");
-        desensitizeDemo.setSlider2("ABCDEFG");
-        desensitizeDemo.setSlider3("ABCDEFG");
-        desensitizeDemo.setEmail("1@email.com");
-        desensitizeDemo.setRegex("你好,我是iailab");
-        desensitizeDemo.setAddress("北京市海淀区上地十街10号");
-        desensitizeDemo.setOrigin("iailab");
-
-        // 调用
-        DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class);
-        // 断言
-        assertNotNull(d);
-        assertEquals("芋***", d.getNickname());
-        assertEquals("998800********31", d.getBankCard());
-        assertEquals("粤A6***6", d.getCarLicense());
-        assertEquals("0108*****22", d.getFixedPhone());
-        assertEquals("530321**********11", d.getIdCard());
-        assertEquals("******", d.getPassword());
-        assertEquals("132****5917", d.getPhoneNumber());
-        assertEquals("#######", d.getSlider1());
-        assertEquals("ABC*EFG", d.getSlider2());
-        assertEquals("*******", d.getSlider3());
-        assertEquals("1****@email.com", d.getEmail());
-        assertEquals("你好,我是*", d.getRegex());
-        assertEquals("北京市海淀区上地十街10号*", d.getAddress());
-        assertEquals("iailab", d.getOrigin());
-    }
-
-    @Data
-    public static class DesensitizeDemo {
-
-        @ChineseNameDesensitize
-        private String nickname;
-        @BankCardDesensitize
-        private String bankCard;
-        @CarLicenseDesensitize
-        private String carLicense;
-        @FixedPhoneDesensitize
-        private String fixedPhone;
-        @IdCardDesensitize
-        private String idCard;
-        @PasswordDesensitize
-        private String password;
-        @MobileDesensitize
-        private String phoneNumber;
-        @SliderDesensitize(prefixKeep = 6, suffixKeep = 1, replacer = "#")
-        private String slider1;
-        @SliderDesensitize(prefixKeep = 3, suffixKeep = 3)
-        private String slider2;
-        @SliderDesensitize(prefixKeep = 10)
-        private String slider3;
-        @EmailDesensitize
-        private String email;
-        @RegexDesensitize(regex = "iailab", replacer = "*")
-        private String regex;
-        @Address
-        private String address;
-        private String origin;
-
-    }
-
-}
diff --git a/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/annotation/Address.java b/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/annotation/Address.java
deleted file mode 100644
index 01826e4..0000000
--- a/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/annotation/Address.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.framework.desensitize.core.annotation;
-
-import com.iailab.framework.desensitize.core.DesensitizeTest;
-import com.iailab.framework.desensitize.core.base.annotation.DesensitizeBy;
-import com.iailab.framework.desensitize.core.handler.AddressHandler;
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 地址
- *
- * 用于 {@link DesensitizeTest} 测试使用
- *
- * @author gaibu
- */
-@Documented
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@JacksonAnnotationsInside
-@DesensitizeBy(handler = AddressHandler.class)
-public @interface Address {
-
-    String replacer() default "*";
-
-}
diff --git a/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/handler/AddressHandler.java b/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/handler/AddressHandler.java
deleted file mode 100644
index 6172c24..0000000
--- a/iailab-framework/iailab-common-web/src/test/java/com/iailab/framework/desensitize/core/handler/AddressHandler.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.framework.desensitize.core.handler;
-
-import com.iailab.framework.desensitize.core.DesensitizeTest;
-import com.iailab.framework.desensitize.core.base.handler.DesensitizationHandler;
-import com.iailab.framework.desensitize.core.annotation.Address;
-
-/**
- * {@link Address} 的脱敏处理器
- *
- * 用于 {@link DesensitizeTest} 测试使用
- */
-public class AddressHandler implements DesensitizationHandler<Address> {
-
-    @Override
-    public String desensitize(String origin, Address annotation) {
-        return origin + annotation.replacer();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/pom.xml b/iailab-framework/iailab-common-websocket/pom.xml
deleted file mode 100644
index a566d80..0000000
--- a/iailab-framework/iailab-common-websocket/pom.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common-websocket</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>WebSocket 框架,支持多节点的广播</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-
-    <dependencies>
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common</artifactId>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <!-- 为什么是 websocket 依赖 security 呢?而不是 security 拓展 websocket 呢?
-                 因为 websocket 和 LoginUser 当前登录的用户有一定的相关性,具体可见 WebSocketSessionManagerImpl 逻辑。
-                 如果让 security 拓展 websocket 的话,会导致 websocket 组件的封装很散,进而增大理解成本。
-            -->
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-security</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-websocket</artifactId>
-        </dependency>
-
-        <!-- 消息队列相关 -->
-        <dependency>
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-mq</artifactId>
-        </dependency>
-<!--        <dependency>-->
-<!--            <groupId>org.springframework.kafka</groupId>-->
-<!--            <artifactId>spring-kafka</artifactId>-->
-<!--            <optional>true</optional>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>org.springframework.amqp</groupId>-->
-<!--            <artifactId>spring-rabbit</artifactId>-->
-<!--            <optional>true</optional>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>org.apache.rocketmq</groupId>-->
-<!--            <artifactId>rocketmq-spring-boot-starter</artifactId>-->
-<!--            <optional>true</optional>-->
-<!--        </dependency>-->
-
-        <!-- 业务组件 -->
-        <dependency>
-            <!-- 为什么要依赖 tenant 组件?
-                因为广播某个类型的用户时候,需要根据租户过滤下,避免广播到别的租户!
-            -->
-            <groupId>com.iailab</groupId>
-            <artifactId>iailab-common-biz-tenant</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-</project>
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/config/IailabWebSocketAutoConfiguration.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/config/IailabWebSocketAutoConfiguration.java
deleted file mode 100644
index 459a5b9..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/config/IailabWebSocketAutoConfiguration.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package com.iailab.framework.websocket.config;
-
-import com.iailab.framework.mq.redis.config.IailabRedisMQConsumerAutoConfiguration;
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.websocket.core.handler.JsonWebSocketMessageHandler;
-import com.iailab.framework.websocket.core.listener.WebSocketMessageListener;
-import com.iailab.framework.websocket.core.security.LoginUserHandshakeInterceptor;
-import com.iailab.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer;
-import com.iailab.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.local.LocalWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.rabbitmq.RabbitMQWebSocketMessageConsumer;
-import com.iailab.framework.websocket.core.sender.rabbitmq.RabbitMQWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.redis.RedisWebSocketMessageConsumer;
-import com.iailab.framework.websocket.core.sender.redis.RedisWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.rocketmq.RocketMQWebSocketMessageConsumer;
-import com.iailab.framework.websocket.core.sender.rocketmq.RocketMQWebSocketMessageSender;
-import com.iailab.framework.websocket.core.session.WebSocketSessionHandlerDecorator;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManagerImpl;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.springframework.amqp.core.TopicExchange;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.kafka.core.KafkaTemplate;
-import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.config.annotation.EnableWebSocket;
-import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
-import org.springframework.web.socket.server.HandshakeInterceptor;
-
-import java.util.List;
-
-/**
- * WebSocket 自动配置
- *
- * @author xingyu4j
- */
-@AutoConfiguration(before = IailabRedisMQConsumerAutoConfiguration.class) // before IailabRedisMQConsumerAutoConfiguration 的原因是,需要保证 RedisWebSocketMessageConsumer 先创建,才能创建 RedisMessageListenerContainer
-@EnableWebSocket // 开启 websocket
-@ConditionalOnProperty(prefix = "iailab.websocket", value = "enable", matchIfMissing = true) // 允许使用 iailab.websocket.enable=false 禁用 websocket
-@EnableConfigurationProperties(WebSocketProperties.class)
-public class IailabWebSocketAutoConfiguration {
-
-    @Bean
-    public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor[] handshakeInterceptors,
-                                                   WebSocketHandler webSocketHandler,
-                                                   WebSocketProperties webSocketProperties) {
-        return registry -> registry
-                // 添加 WebSocketHandler
-                .addHandler(webSocketHandler, webSocketProperties.getPath())
-                .addInterceptors(handshakeInterceptors)
-                // 允许跨域,否则前端连接会直接断开
-                .setAllowedOriginPatterns("*");
-    }
-
-    @Bean
-    public HandshakeInterceptor handshakeInterceptor() {
-        return new LoginUserHandshakeInterceptor();
-    }
-
-    @Bean
-    public WebSocketHandler webSocketHandler(WebSocketSessionManager sessionManager,
-                                             List<? extends WebSocketMessageListener<?>> messageListeners) {
-        // 1. 创建 JsonWebSocketMessageHandler 对象,处理消息
-        JsonWebSocketMessageHandler messageHandler = new JsonWebSocketMessageHandler(messageListeners);
-        // 2. 创建 WebSocketSessionHandlerDecorator 对象,处理连接
-        return new WebSocketSessionHandlerDecorator(messageHandler, sessionManager);
-    }
-
-    @Bean
-    public WebSocketSessionManager webSocketSessionManager() {
-        return new WebSocketSessionManagerImpl();
-    }
-
-    // ==================== Sender 相关 ====================
-
-    @Configuration
-    @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "local", matchIfMissing = true)
-    public class LocalWebSocketMessageSenderConfiguration {
-
-        @Bean
-        public LocalWebSocketMessageSender localWebSocketMessageSender(WebSocketSessionManager sessionManager) {
-            return new LocalWebSocketMessageSender(sessionManager);
-        }
-
-    }
-
-    @Configuration
-    @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "redis", matchIfMissing = true)
-    public class RedisWebSocketMessageSenderConfiguration {
-
-        @Bean
-        public RedisWebSocketMessageSender redisWebSocketMessageSender(WebSocketSessionManager sessionManager,
-                                                                       RedisMQTemplate redisMQTemplate) {
-            return new RedisWebSocketMessageSender(sessionManager, redisMQTemplate);
-        }
-
-        @Bean
-        public RedisWebSocketMessageConsumer redisWebSocketMessageConsumer(
-                RedisWebSocketMessageSender redisWebSocketMessageSender) {
-            return new RedisWebSocketMessageConsumer(redisWebSocketMessageSender);
-        }
-
-    }
-
-    @Configuration
-    @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "rocketmq", matchIfMissing = true)
-    public class RocketMQWebSocketMessageSenderConfiguration {
-
-        @Bean
-        public RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender(
-                WebSocketSessionManager sessionManager, RocketMQTemplate rocketMQTemplate,
-                @Value("${iailab.websocket.sender-rocketmq.topic}") String topic) {
-            return new RocketMQWebSocketMessageSender(sessionManager, rocketMQTemplate, topic);
-        }
-
-        @Bean
-        public RocketMQWebSocketMessageConsumer rocketMQWebSocketMessageConsumer(
-                RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender) {
-            return new RocketMQWebSocketMessageConsumer(rocketMQWebSocketMessageSender);
-        }
-
-    }
-
-    @Configuration
-    @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "rabbitmq", matchIfMissing = true)
-    public class RabbitMQWebSocketMessageSenderConfiguration {
-
-        @Bean
-        public RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender(
-                WebSocketSessionManager sessionManager, RabbitTemplate rabbitTemplate,
-                TopicExchange websocketTopicExchange) {
-            return new RabbitMQWebSocketMessageSender(sessionManager, rabbitTemplate, websocketTopicExchange);
-        }
-
-        @Bean
-        public RabbitMQWebSocketMessageConsumer rabbitMQWebSocketMessageConsumer(
-                RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender) {
-            return new RabbitMQWebSocketMessageConsumer(rabbitMQWebSocketMessageSender);
-        }
-
-        /**
-         * 创建 Topic Exchange
-         */
-        @Bean
-        public TopicExchange websocketTopicExchange(@Value("${iailab.websocket.sender-rabbitmq.exchange}") String exchange) {
-            return new TopicExchange(exchange,
-                    true,  // durable: 是否持久化
-                    false);  // exclusive: 是否排它
-        }
-
-    }
-
-    @Configuration
-    @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "kafka", matchIfMissing = true)
-    public class KafkaWebSocketMessageSenderConfiguration {
-
-        @Bean
-        public KafkaWebSocketMessageSender kafkaWebSocketMessageSender(
-                WebSocketSessionManager sessionManager, KafkaTemplate<Object, Object> kafkaTemplate,
-                @Value("${iailab.websocket.sender-kafka.topic}") String topic) {
-            return new KafkaWebSocketMessageSender(sessionManager, kafkaTemplate, topic);
-        }
-
-        @Bean
-        public KafkaWebSocketMessageConsumer kafkaWebSocketMessageConsumer(
-                KafkaWebSocketMessageSender kafkaWebSocketMessageSender) {
-            return new KafkaWebSocketMessageConsumer(kafkaWebSocketMessageSender);
-        }
-
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/config/WebSocketProperties.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/config/WebSocketProperties.java
deleted file mode 100644
index 75e10ca..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/config/WebSocketProperties.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.iailab.framework.websocket.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-/**
- * WebSocket 配置项
- *
- * @author xingyu4j
- */
-@ConfigurationProperties("iailab.websocket")
-@Data
-@Validated
-public class WebSocketProperties {
-
-    /**
-     * WebSocket 的连接路径
-     */
-    @NotEmpty(message = "WebSocket 的连接路径不能为空")
-    private String path = "/ws";
-
-    /**
-     * 消息发送器的类型
-     *
-     * 可选值:local、redis、rocketmq、kafka、rabbitmq
-     */
-    @NotNull(message = "WebSocket 的消息发送者不能为空")
-    private String senderType = "local";
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/handler/JsonWebSocketMessageHandler.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/handler/JsonWebSocketMessageHandler.java
deleted file mode 100644
index 699e282..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/handler/JsonWebSocketMessageHandler.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.iailab.framework.websocket.core.handler;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.core.util.TypeUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.tenant.core.util.TenantUtils;
-import com.iailab.framework.websocket.core.listener.WebSocketMessageListener;
-import com.iailab.framework.websocket.core.message.JsonWebSocketMessage;
-import com.iailab.framework.websocket.core.util.WebSocketFrameworkUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.socket.TextMessage;
-import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.WebSocketSession;
-import org.springframework.web.socket.handler.TextWebSocketHandler;
-
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Consumer;
-
-/**
- * JSON 格式 {@link WebSocketHandler} 实现类
- *
- * 基于 {@link JsonWebSocketMessage#getType()} 消息类型,调度到对应的 {@link WebSocketMessageListener} 监听器。
- *
- * @author iailab
- */
-@Slf4j
-public class JsonWebSocketMessageHandler extends TextWebSocketHandler {
-
-    /**
-     * type 与 WebSocketMessageListener 的映射
-     */
-    private final Map<String, WebSocketMessageListener<Object>> listeners = new HashMap<>();
-
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    public JsonWebSocketMessageHandler(List<? extends WebSocketMessageListener> listenersList) {
-        listenersList.forEach((Consumer<WebSocketMessageListener>)
-                listener -> listeners.put(listener.getType(), listener));
-    }
-
-    @Override
-    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
-        // 1.1 空消息,跳过
-        if (message.getPayloadLength() == 0) {
-            return;
-        }
-        // 1.2 ping 心跳消息,直接返回 pong 消息。
-        if (message.getPayloadLength() == 4 && Objects.equals(message.getPayload(), "ping")) {
-            session.sendMessage(new TextMessage("pong"));
-            return;
-        }
-
-        // 2.1 解析消息
-        try {
-            JsonWebSocketMessage jsonMessage = JsonUtils.parseObject(message.getPayload(), JsonWebSocketMessage.class);
-            if (jsonMessage == null) {
-                log.error("[handleTextMessage][session({}) message({}) 解析为空]", session.getId(), message.getPayload());
-                return;
-            }
-            if (StrUtil.isEmpty(jsonMessage.getType())) {
-                log.error("[handleTextMessage][session({}) message({}) 类型为空]", session.getId(), message.getPayload());
-                return;
-            }
-            // 2.2 获得对应的 WebSocketMessageListener
-            WebSocketMessageListener<Object> messageListener = listeners.get(jsonMessage.getType());
-            if (messageListener == null) {
-                log.error("[handleTextMessage][session({}) message({}) 监听器为空]", session.getId(), message.getPayload());
-                return;
-            }
-            // 2.3 处理消息
-            Type type = TypeUtil.getTypeArgument(messageListener.getClass(), 0);
-            Object messageObj = JsonUtils.parseObject(jsonMessage.getContent(), type);
-            Long tenantId = WebSocketFrameworkUtils.getTenantId(session);
-            TenantUtils.execute(tenantId, () -> messageListener.onMessage(session, messageObj));
-        } catch (Throwable ex) {
-            log.error("[handleTextMessage][session({}) message({}) 处理异常]", session.getId(), message.getPayload());
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/listener/WebSocketMessageListener.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/listener/WebSocketMessageListener.java
deleted file mode 100644
index 9b55317..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/listener/WebSocketMessageListener.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.iailab.framework.websocket.core.listener;
-
-import com.iailab.framework.websocket.core.message.JsonWebSocketMessage;
-import org.springframework.web.socket.WebSocketSession;
-
-/**
- * WebSocket 消息监听器接口
- *
- * 目的:前端发送消息给后端后,处理对应 {@link #getType()} 类型的消息
- *
- * @param <T> 泛型,消息类型
- */
-public interface WebSocketMessageListener<T> {
-
-    /**
-     * 处理消息
-     *
-     * @param session Session
-     * @param message 消息
-     */
-    void onMessage(WebSocketSession session, T message);
-
-    /**
-     * 获得消息类型
-     *
-     * @see JsonWebSocketMessage#getType()
-     * @return 消息类型
-     */
-    String getType();
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/message/JsonWebSocketMessage.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/message/JsonWebSocketMessage.java
deleted file mode 100644
index e9c598f..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/message/JsonWebSocketMessage.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.iailab.framework.websocket.core.message;
-
-import com.iailab.framework.websocket.core.listener.WebSocketMessageListener;
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * JSON 格式的 WebSocket 消息帧
- *
- * @author iailab
- */
-@Data
-public class JsonWebSocketMessage implements Serializable {
-
-    /**
-     * 消息类型
-     *
-     * 目的:用于分发到对应的 {@link WebSocketMessageListener} 实现类
-     */
-    private String type;
-    /**
-     * 消息内容
-     *
-     * 要求 JSON 对象
-     */
-    private String content;
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/security/LoginUserHandshakeInterceptor.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/security/LoginUserHandshakeInterceptor.java
deleted file mode 100644
index d1092f5..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/security/LoginUserHandshakeInterceptor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.framework.websocket.core.security;
-
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.security.core.filter.TokenAuthenticationFilter;
-import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.framework.websocket.core.util.WebSocketFrameworkUtils;
-import org.springframework.http.server.ServerHttpRequest;
-import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.WebSocketSession;
-import org.springframework.web.socket.server.HandshakeInterceptor;
-
-import java.util.Map;
-
-/**
- * 登录用户的 {@link HandshakeInterceptor} 实现类
- *
- * 流程如下:
- * 1. 前端连接 websocket 时,会通过拼接 ?token={token} 到 ws:// 连接后,这样它可以被 {@link TokenAuthenticationFilter} 所认证通过
- * 2. {@link LoginUserHandshakeInterceptor} 负责把 {@link LoginUser} 添加到 {@link WebSocketSession} 中
- *
- * @author iailab
- */
-public class LoginUserHandshakeInterceptor implements HandshakeInterceptor {
-
-    @Override
-    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
-                                   WebSocketHandler wsHandler, Map<String, Object> attributes) {
-        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
-        if (loginUser != null) {
-            WebSocketFrameworkUtils.setLoginUser(loginUser, attributes);
-        }
-        return true;
-    }
-
-    @Override
-    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
-                               WebSocketHandler wsHandler, Exception exception) {
-        // do nothing
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/security/WebSocketAuthorizeRequestsCustomizer.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/security/WebSocketAuthorizeRequestsCustomizer.java
deleted file mode 100644
index bd760f5..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/security/WebSocketAuthorizeRequestsCustomizer.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.iailab.framework.websocket.core.security;
-
-import com.iailab.framework.security.config.AuthorizeRequestsCustomizer;
-import com.iailab.framework.websocket.config.WebSocketProperties;
-import lombok.RequiredArgsConstructor;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
-
-/**
- * WebSocket 的权限自定义
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public class WebSocketAuthorizeRequestsCustomizer extends AuthorizeRequestsCustomizer {
-
-    private final WebSocketProperties webSocketProperties;
-
-    @Override
-    public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
-        registry.requestMatchers(webSocketProperties.getPath()).permitAll();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/AbstractWebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/AbstractWebSocketMessageSender.java
deleted file mode 100644
index ce676f0..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/AbstractWebSocketMessageSender.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.iailab.framework.websocket.core.sender;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.framework.websocket.core.message.JsonWebSocketMessage;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.socket.TextMessage;
-import org.springframework.web.socket.WebSocketSession;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * WebSocketMessageSender 实现类
- *
- * @author iailab
- */
-@Slf4j
-@RequiredArgsConstructor
-public abstract class AbstractWebSocketMessageSender implements WebSocketMessageSender {
-
-    private final WebSocketSessionManager sessionManager;
-
-    @Override
-    public void send(Integer userType, Long userId, String messageType, String messageContent) {
-        send(null, userType, userId, messageType, messageContent);
-    }
-
-    @Override
-    public void send(Integer userType, String messageType, String messageContent) {
-        send(null, userType, null, messageType, messageContent);
-    }
-
-    @Override
-    public void send(String sessionId, String messageType, String messageContent) {
-        send(sessionId, null, null, messageType, messageContent);
-    }
-
-    /**
-     * 发送消息
-     *
-     * @param sessionId Session 编号
-     * @param userType 用户类型
-     * @param userId 用户编号
-     * @param messageType 消息类型
-     * @param messageContent 消息内容
-     */
-    public void send(String sessionId, Integer userType, Long userId, String messageType, String messageContent) {
-        // 1. 获得 Session 列表
-        List<WebSocketSession> sessions = Collections.emptyList();
-        if (StrUtil.isNotEmpty(sessionId)) {
-            WebSocketSession session = sessionManager.getSession(sessionId);
-            if (session != null) {
-                sessions = Collections.singletonList(session);
-            }
-        } else if (userType != null && userId != null) {
-            sessions = (List<WebSocketSession>) sessionManager.getSessionList(userType, userId);
-        } else if (userType != null) {
-            sessions = (List<WebSocketSession>) sessionManager.getSessionList(userType);
-        }
-        if (CollUtil.isEmpty(sessions)) {
-            log.info("[send][sessionId({}) userType({}) userId({}) messageType({}) messageContent({}) 未匹配到会话]",
-                    sessionId, userType, userId, messageType, messageContent);
-        }
-        // 2. 执行发送
-        doSend(sessions, messageType, messageContent);
-    }
-
-    /**
-     * 发送消息的具体实现
-     *
-     * @param sessions Session 列表
-     * @param messageType 消息类型
-     * @param messageContent 消息内容
-     */
-    public void doSend(Collection<WebSocketSession> sessions, String messageType, String messageContent) {
-        JsonWebSocketMessage message = new JsonWebSocketMessage().setType(messageType).setContent(messageContent);
-        String payload = JsonUtils.toJsonString(message); // 关键,使用 JSON 序列化
-        sessions.forEach(session -> {
-            // 1. 各种校验,保证 Session 可以被发送
-            if (session == null) {
-                log.error("[doSend][session 为空, message({})]", message);
-                return;
-            }
-            if (!session.isOpen()) {
-                log.error("[doSend][session({}) 已关闭, message({})]", session.getId(), message);
-                return;
-            }
-            // 2. 执行发送
-            try {
-                session.sendMessage(new TextMessage(payload));
-                log.info("[doSend][session({}) 发送消息成功,message({})]", session.getId(), message);
-            } catch (IOException ex) {
-                log.error("[doSend][session({}) 发送消息失败,message({})]", session.getId(), message, ex);
-            }
-        });
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/WebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/WebSocketMessageSender.java
deleted file mode 100644
index df5f111..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/WebSocketMessageSender.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.iailab.framework.websocket.core.sender;
-
-import com.iailab.framework.common.util.json.JsonUtils;
-
-/**
- * WebSocket 消息的发送器接口
- *
- * @author iailab
- */
-public interface WebSocketMessageSender {
-
-    /**
-     * 发送消息给指定用户
-     *
-     * @param userType 用户类型
-     * @param userId 用户编号
-     * @param messageType 消息类型
-     * @param messageContent 消息内容,JSON 格式
-     */
-    void send(Integer userType, Long userId, String messageType, String messageContent);
-
-    /**
-     * 发送消息给指定用户类型
-     *
-     * @param userType 用户类型
-     * @param messageType 消息类型
-     * @param messageContent 消息内容,JSON 格式
-     */
-    void send(Integer userType, String messageType, String messageContent);
-
-    /**
-     * 发送消息给指定 Session
-     *
-     * @param sessionId Session 编号
-     * @param messageType 消息类型
-     * @param messageContent 消息内容,JSON 格式
-     */
-    void send(String sessionId, String messageType, String messageContent);
-
-    default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) {
-        send(userType, userId, messageType, JsonUtils.toJsonString(messageContent));
-    }
-
-    default void sendObject(Integer userType, String messageType, Object messageContent) {
-        send(userType, messageType, JsonUtils.toJsonString(messageContent));
-    }
-
-    default void sendObject(String sessionId, String messageType, Object messageContent) {
-        send(sessionId, messageType, JsonUtils.toJsonString(messageContent));
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessage.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessage.java
deleted file mode 100644
index a61a6c9..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.websocket.core.sender.kafka;
-
-import lombok.Data;
-
-/**
- * Kafka 广播 WebSocket 的消息
- *
- * @author iailab
- */
-@Data
-public class KafkaWebSocketMessage {
-
-    /**
-     * Session 编号
-     */
-    private String sessionId;
-    /**
-     * 用户类型
-     */
-    private Integer userType;
-    /**
-     * 用户编号
-     */
-    private Long userId;
-
-    /**
-     * 消息类型
-     */
-    private String messageType;
-    /**
-     * 消息内容
-     */
-    private String messageContent;
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessageConsumer.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessageConsumer.java
deleted file mode 100644
index ffad2f8..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessageConsumer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.websocket.core.sender.kafka;
-
-import lombok.RequiredArgsConstructor;
-import org.springframework.amqp.rabbit.annotation.RabbitHandler;
-import org.springframework.kafka.annotation.KafkaListener;
-
-/**
- * {@link KafkaWebSocketMessage} 广播消息的消费者,真正把消息发送出去
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public class KafkaWebSocketMessageConsumer {
-
-    private final KafkaWebSocketMessageSender rabbitMQWebSocketMessageSender;
-
-    @RabbitHandler
-    @KafkaListener(
-            topics = "${iailab.websocket.sender-kafka.topic}",
-            // 在 Group 上,使用 UUID 生成其后缀。这样,启动的 Consumer 的 Group 不同,以达到广播消费的目的
-            groupId = "${iailab.websocket.sender-kafka.consumer-group}" + "-" + "#{T(java.util.UUID).randomUUID()}")
-    public void onMessage(KafkaWebSocketMessage message) {
-        rabbitMQWebSocketMessageSender.send(message.getSessionId(),
-                message.getUserType(), message.getUserId(),
-                message.getMessageType(), message.getMessageContent());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessageSender.java
deleted file mode 100644
index 8801a55..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/kafka/KafkaWebSocketMessageSender.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.iailab.framework.websocket.core.sender.kafka;
-
-import com.iailab.framework.websocket.core.sender.AbstractWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.WebSocketMessageSender;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.kafka.core.KafkaTemplate;
-
-import java.util.concurrent.ExecutionException;
-
-/**
- * 基于 Kafka 的 {@link WebSocketMessageSender} 实现类
- *
- * @author iailab
- */
-@Slf4j
-public class KafkaWebSocketMessageSender extends AbstractWebSocketMessageSender {
-
-    private final KafkaTemplate<Object, Object> kafkaTemplate;
-
-    private final String topic;
-
-    public KafkaWebSocketMessageSender(WebSocketSessionManager sessionManager,
-                                       KafkaTemplate<Object, Object> kafkaTemplate,
-                                       String topic) {
-        super(sessionManager);
-        this.kafkaTemplate = kafkaTemplate;
-        this.topic = topic;
-    }
-
-    @Override
-    public void send(Integer userType, Long userId, String messageType, String messageContent) {
-        sendKafkaMessage(null, userId, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(Integer userType, String messageType, String messageContent) {
-        sendKafkaMessage(null, null, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(String sessionId, String messageType, String messageContent) {
-        sendKafkaMessage(sessionId, null, null, messageType, messageContent);
-    }
-
-    /**
-     * 通过 Kafka 广播消息
-     *
-     * @param sessionId Session 编号
-     * @param userId 用户编号
-     * @param userType 用户类型
-     * @param messageType 消息类型
-     * @param messageContent 消息内容
-     */
-    private void sendKafkaMessage(String sessionId, Long userId, Integer userType,
-                                  String messageType, String messageContent) {
-        KafkaWebSocketMessage mqMessage = new KafkaWebSocketMessage()
-                .setSessionId(sessionId).setUserId(userId).setUserType(userType)
-                .setMessageType(messageType).setMessageContent(messageContent);
-        try {
-            kafkaTemplate.send(topic, mqMessage).get();
-        } catch (InterruptedException | ExecutionException e) {
-            log.error("[sendKafkaMessage][发送消息({}) 到 Kafka 失败]", mqMessage, e);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/local/LocalWebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/local/LocalWebSocketMessageSender.java
deleted file mode 100644
index 87eaa3c..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/local/LocalWebSocketMessageSender.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.iailab.framework.websocket.core.sender.local;
-
-import com.iailab.framework.websocket.core.sender.AbstractWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.WebSocketMessageSender;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-
-/**
- * 本地的 {@link WebSocketMessageSender} 实现类
- *
- * 注意:仅仅适合单机场景!!!
- *
- * @author iailab
- */
-public class LocalWebSocketMessageSender extends AbstractWebSocketMessageSender {
-
-    public LocalWebSocketMessageSender(WebSocketSessionManager sessionManager) {
-        super(sessionManager);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessage.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessage.java
deleted file mode 100644
index 02abb91..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessage.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.websocket.core.sender.rabbitmq;
-
-import lombok.Data;
-
-import java.io.Serializable;
-
-/**
- * RabbitMQ 广播 WebSocket 的消息
- *
- * @author iailab
- */
-@Data
-public class RabbitMQWebSocketMessage implements Serializable {
-
-    /**
-     * Session 编号
-     */
-    private String sessionId;
-    /**
-     * 用户类型
-     */
-    private Integer userType;
-    /**
-     * 用户编号
-     */
-    private Long userId;
-
-    /**
-     * 消息类型
-     */
-    private String messageType;
-    /**
-     * 消息内容
-     */
-    private String messageContent;
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageConsumer.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageConsumer.java
deleted file mode 100644
index 9505bfb..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageConsumer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.framework.websocket.core.sender.rabbitmq;
-
-import lombok.RequiredArgsConstructor;
-import org.springframework.amqp.core.ExchangeTypes;
-import org.springframework.amqp.rabbit.annotation.*;
-
-/**
- * {@link RabbitMQWebSocketMessage} 广播消息的消费者,真正把消息发送出去
- *
- * @author iailab
- */
-@RabbitListener(
-        bindings = @QueueBinding(
-                value = @Queue(
-                        // 在 Queue 的名字上,使用 UUID 生成其后缀。这样,启动的 Consumer 的 Queue 不同,以达到广播消费的目的
-                        name = "${iailab.websocket.sender-rabbitmq.queue}" + "-" + "#{T(java.util.UUID).randomUUID()}",
-                        // Consumer 关闭时,该队列就可以被自动删除了
-                        autoDelete = "true"
-                ),
-                exchange = @Exchange(
-                        name = "${iailab.websocket.sender-rabbitmq.exchange}",
-                        type = ExchangeTypes.TOPIC,
-                        declare = "false"
-                )
-        )
-)
-@RequiredArgsConstructor
-public class RabbitMQWebSocketMessageConsumer {
-
-    private final RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender;
-
-    @RabbitHandler
-    public void onMessage(RabbitMQWebSocketMessage message) {
-        rabbitMQWebSocketMessageSender.send(message.getSessionId(),
-                message.getUserType(), message.getUserId(),
-                message.getMessageType(), message.getMessageContent());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageSender.java
deleted file mode 100644
index f3e1409..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageSender.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.iailab.framework.websocket.core.sender.rabbitmq;
-
-import com.iailab.framework.websocket.core.sender.AbstractWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.WebSocketMessageSender;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.amqp.core.TopicExchange;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
-
-/**
- * 基于 RabbitMQ 的 {@link WebSocketMessageSender} 实现类
- *
- * @author iailab
- */
-@Slf4j
-public class RabbitMQWebSocketMessageSender extends AbstractWebSocketMessageSender {
-
-    private final RabbitTemplate rabbitTemplate;
-
-    private final TopicExchange topicExchange;
-
-    public RabbitMQWebSocketMessageSender(WebSocketSessionManager sessionManager,
-                                          RabbitTemplate rabbitTemplate,
-                                          TopicExchange topicExchange) {
-        super(sessionManager);
-        this.rabbitTemplate = rabbitTemplate;
-        this.topicExchange = topicExchange;
-    }
-
-    @Override
-    public void send(Integer userType, Long userId, String messageType, String messageContent) {
-        sendRabbitMQMessage(null, userId, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(Integer userType, String messageType, String messageContent) {
-        sendRabbitMQMessage(null, null, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(String sessionId, String messageType, String messageContent) {
-        sendRabbitMQMessage(sessionId, null, null, messageType, messageContent);
-    }
-
-    /**
-     * 通过 RabbitMQ 广播消息
-     *
-     * @param sessionId Session 编号
-     * @param userId 用户编号
-     * @param userType 用户类型
-     * @param messageType 消息类型
-     * @param messageContent 消息内容
-     */
-    private void sendRabbitMQMessage(String sessionId, Long userId, Integer userType,
-                                     String messageType, String messageContent) {
-        RabbitMQWebSocketMessage mqMessage = new RabbitMQWebSocketMessage()
-                .setSessionId(sessionId).setUserId(userId).setUserType(userType)
-                .setMessageType(messageType).setMessageContent(messageContent);
-        rabbitTemplate.convertAndSend(topicExchange.getName(), null, mqMessage);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessage.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessage.java
deleted file mode 100644
index dddf1ef..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessage.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.iailab.framework.websocket.core.sender.redis;
-
-import com.iailab.framework.mq.redis.core.pubsub.AbstractRedisChannelMessage;
-import lombok.Data;
-
-/**
- * Redis 广播 WebSocket 的消息
- */
-@Data
-public class RedisWebSocketMessage extends AbstractRedisChannelMessage {
-
-    /**
-     * Session 编号
-     */
-    private String sessionId;
-    /**
-     * 用户类型
-     */
-    private Integer userType;
-    /**
-     * 用户编号
-     */
-    private Long userId;
-
-    /**
-     * 消息类型
-     */
-    private String messageType;
-    /**
-     * 消息内容
-     */
-    private String messageContent;
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessageConsumer.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessageConsumer.java
deleted file mode 100644
index 228964c..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessageConsumer.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.iailab.framework.websocket.core.sender.redis;
-
-import com.iailab.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
-import lombok.RequiredArgsConstructor;
-
-/**
- * {@link RedisWebSocketMessage} 广播消息的消费者,真正把消息发送出去
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-public class RedisWebSocketMessageConsumer extends AbstractRedisChannelMessageListener<RedisWebSocketMessage> {
-
-    private final RedisWebSocketMessageSender redisWebSocketMessageSender;
-
-    @Override
-    public void onMessage(RedisWebSocketMessage message) {
-        redisWebSocketMessageSender.send(message.getSessionId(),
-                message.getUserType(), message.getUserId(),
-                message.getMessageType(), message.getMessageContent());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessageSender.java
deleted file mode 100644
index 5d400a1..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/redis/RedisWebSocketMessageSender.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.iailab.framework.websocket.core.sender.redis;
-
-import com.iailab.framework.mq.redis.core.RedisMQTemplate;
-import com.iailab.framework.websocket.core.sender.AbstractWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.WebSocketMessageSender;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 基于 Redis 的 {@link WebSocketMessageSender} 实现类
- *
- * @author iailab
- */
-@Slf4j
-public class RedisWebSocketMessageSender extends AbstractWebSocketMessageSender {
-
-    private final RedisMQTemplate redisMQTemplate;
-
-    public RedisWebSocketMessageSender(WebSocketSessionManager sessionManager,
-                                       RedisMQTemplate redisMQTemplate) {
-        super(sessionManager);
-        this.redisMQTemplate = redisMQTemplate;
-    }
-
-    @Override
-    public void send(Integer userType, Long userId, String messageType, String messageContent) {
-        sendRedisMessage(null, userId, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(Integer userType, String messageType, String messageContent) {
-        sendRedisMessage(null, null, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(String sessionId, String messageType, String messageContent) {
-        sendRedisMessage(sessionId, null, null, messageType, messageContent);
-    }
-
-    /**
-     * 通过 Redis 广播消息
-     *
-     * @param sessionId Session 编号
-     * @param userId 用户编号
-     * @param userType 用户类型
-     * @param messageType 消息类型
-     * @param messageContent 消息内容
-     */
-    private void sendRedisMessage(String sessionId, Long userId, Integer userType,
-                                  String messageType, String messageContent) {
-        RedisWebSocketMessage mqMessage = new RedisWebSocketMessage()
-                .setSessionId(sessionId).setUserId(userId).setUserType(userType)
-                .setMessageType(messageType).setMessageContent(messageContent);
-        redisMQTemplate.send(mqMessage);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessage.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessage.java
deleted file mode 100644
index 92dc515..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.websocket.core.sender.rocketmq;
-
-import lombok.Data;
-
-/**
- * RocketMQ 广播 WebSocket 的消息
- *
- * @author iailab
- */
-@Data
-public class RocketMQWebSocketMessage {
-
-    /**
-     * Session 编号
-     */
-    private String sessionId;
-    /**
-     * 用户类型
-     */
-    private Integer userType;
-    /**
-     * 用户编号
-     */
-    private Long userId;
-
-    /**
-     * 消息类型
-     */
-    private String messageType;
-    /**
-     * 消息内容
-     */
-    private String messageContent;
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageConsumer.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageConsumer.java
deleted file mode 100644
index 38b7836..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageConsumer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.framework.websocket.core.sender.rocketmq;
-
-import lombok.RequiredArgsConstructor;
-import org.apache.rocketmq.spring.annotation.MessageModel;
-import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
-import org.apache.rocketmq.spring.core.RocketMQListener;
-
-/**
- * {@link RocketMQWebSocketMessage} 广播消息的消费者,真正把消息发送出去
- *
- * @author iailab
- */
-@RocketMQMessageListener( // 重点:添加 @RocketMQMessageListener 注解,声明消费的 topic
-        topic = "${iailab.websocket.sender-rocketmq.topic}",
-        consumerGroup = "${iailab.websocket.sender-rocketmq.consumer-group}",
-        messageModel = MessageModel.BROADCASTING // 设置为广播模式,保证每个实例都能收到消息
-)
-@RequiredArgsConstructor
-public class RocketMQWebSocketMessageConsumer implements RocketMQListener<RocketMQWebSocketMessage> {
-
-    private final RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender;
-
-    @Override
-    public void onMessage(RocketMQWebSocketMessage message) {
-        rocketMQWebSocketMessageSender.send(message.getSessionId(),
-                message.getUserType(), message.getUserId(),
-                message.getMessageType(), message.getMessageContent());
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageSender.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageSender.java
deleted file mode 100644
index 2241b13..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageSender.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.iailab.framework.websocket.core.sender.rocketmq;
-
-import com.iailab.framework.websocket.core.sender.AbstractWebSocketMessageSender;
-import com.iailab.framework.websocket.core.sender.WebSocketMessageSender;
-import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-
-/**
- * 基于 RocketMQ 的 {@link WebSocketMessageSender} 实现类
- *
- * @author iailab
- */
-@Slf4j
-public class RocketMQWebSocketMessageSender extends AbstractWebSocketMessageSender {
-
-    private final RocketMQTemplate rocketMQTemplate;
-
-    private final String topic;
-
-    public RocketMQWebSocketMessageSender(WebSocketSessionManager sessionManager,
-                                          RocketMQTemplate rocketMQTemplate,
-                                          String topic) {
-        super(sessionManager);
-        this.rocketMQTemplate = rocketMQTemplate;
-        this.topic = topic;
-    }
-
-    @Override
-    public void send(Integer userType, Long userId, String messageType, String messageContent) {
-        sendRocketMQMessage(null, userId, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(Integer userType, String messageType, String messageContent) {
-        sendRocketMQMessage(null, null, userType, messageType, messageContent);
-    }
-
-    @Override
-    public void send(String sessionId, String messageType, String messageContent) {
-        sendRocketMQMessage(sessionId, null, null, messageType, messageContent);
-    }
-
-    /**
-     * 通过 RocketMQ 广播消息
-     *
-     * @param sessionId Session 编号
-     * @param userId 用户编号
-     * @param userType 用户类型
-     * @param messageType 消息类型
-     * @param messageContent 消息内容
-     */
-    private void sendRocketMQMessage(String sessionId, Long userId, Integer userType,
-                                     String messageType, String messageContent) {
-        RocketMQWebSocketMessage mqMessage = new RocketMQWebSocketMessage()
-                .setSessionId(sessionId).setUserId(userId).setUserType(userType)
-                .setMessageType(messageType).setMessageContent(messageContent);
-        rocketMQTemplate.syncSend(topic, mqMessage);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionHandlerDecorator.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionHandlerDecorator.java
deleted file mode 100644
index 9836e56..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionHandlerDecorator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.iailab.framework.websocket.core.session;
-
-import org.springframework.web.socket.CloseStatus;
-import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.WebSocketSession;
-import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator;
-import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
-
-/**
- * {@link WebSocketHandler} 的装饰类,实现了以下功能:
- *
- * 1. {@link WebSocketSession} 连接或关闭时,使用 {@link #sessionManager} 进行管理
- * 2. 封装 {@link WebSocketSession} 支持并发操作
- *
- * @author iailab
- */
-public class WebSocketSessionHandlerDecorator extends WebSocketHandlerDecorator {
-
-    /**
-     * 发送时间的限制,单位:毫秒
-     */
-    private static final Integer SEND_TIME_LIMIT = 1000 * 5;
-    /**
-     * 发送消息缓冲上线,单位:bytes
-     */
-    private static final Integer BUFFER_SIZE_LIMIT = 1024 * 100;
-
-    private final WebSocketSessionManager sessionManager;
-
-    public WebSocketSessionHandlerDecorator(WebSocketHandler delegate,
-                                            WebSocketSessionManager sessionManager) {
-        super(delegate);
-        this.sessionManager = sessionManager;
-    }
-
-    @Override
-    public void afterConnectionEstablished(WebSocketSession session) {
-        // 实现 session 支持并发,可参考 https://blog.csdn.net/abu935009066/article/details/131218149
-        session = new ConcurrentWebSocketSessionDecorator(session, SEND_TIME_LIMIT, BUFFER_SIZE_LIMIT);
-        // 添加到 WebSocketSessionManager 中
-        sessionManager.addSession(session);
-    }
-
-    @Override
-    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
-        sessionManager.removeSession(session);
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionManager.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionManager.java
deleted file mode 100644
index ad2608a..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionManager.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.iailab.framework.websocket.core.session;
-
-import org.springframework.web.socket.WebSocketSession;
-
-import java.util.Collection;
-
-/**
- * {@link WebSocketSession} 管理器的接口
- *
- * @author iailab
- */
-public interface WebSocketSessionManager {
-
-    /**
-     * 添加 Session
-     *
-     * @param session Session
-     */
-    void addSession(WebSocketSession session);
-
-    /**
-     * 移除 Session
-     *
-     * @param session Session
-     */
-    void removeSession(WebSocketSession session);
-
-    /**
-     * 获得指定编号的 Session
-     *
-     * @param id Session 编号
-     * @return Session
-     */
-    WebSocketSession getSession(String id);
-
-    /**
-     * 获得指定用户类型的 Session 列表
-     *
-     * @param userType 用户类型
-     * @return Session 列表
-     */
-    Collection<WebSocketSession> getSessionList(Integer userType);
-
-    /**
-     * 获得指定用户编号的 Session 列表
-     *
-     * @param userType 用户类型
-     * @param userId 用户编号
-     * @return Session 列表
-     */
-    Collection<WebSocketSession> getSessionList(Integer userType, Long userId);
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionManagerImpl.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionManagerImpl.java
deleted file mode 100644
index 418ec88..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/session/WebSocketSessionManagerImpl.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.iailab.framework.websocket.core.session;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.security.core.LoginUser;
-import com.iailab.framework.tenant.core.context.TenantContextHolder;
-import com.iailab.framework.websocket.core.util.WebSocketFrameworkUtils;
-import org.springframework.web.socket.WebSocketSession;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * 默认的 {@link WebSocketSessionManager} 实现类
- *
- * @author iailab
- */
-public class WebSocketSessionManagerImpl implements WebSocketSessionManager {
-
-    /**
-     * id 与 WebSocketSession 映射
-     *
-     * key:Session 编号
-     */
-    private final ConcurrentMap<String, WebSocketSession> idSessions = new ConcurrentHashMap<>();
-
-    /**
-     * user 与 WebSocketSession 映射
-     *
-     * key1:用户类型
-     * key2:用户编号
-     */
-    private final ConcurrentMap<Integer, ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>>> userSessions
-            = new ConcurrentHashMap<>();
-
-    @Override
-    public void addSession(WebSocketSession session) {
-        // 添加到 idSessions 中
-        idSessions.put(session.getId(), session);
-        // 添加到 userSessions 中
-        LoginUser user = WebSocketFrameworkUtils.getLoginUser(session);
-        if (user == null) {
-            return;
-        }
-        ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(user.getUserType());
-        if (userSessionsMap == null) {
-            userSessionsMap = new ConcurrentHashMap<>();
-            if (userSessions.putIfAbsent(user.getUserType(), userSessionsMap) != null) {
-                userSessionsMap = userSessions.get(user.getUserType());
-            }
-        }
-        CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(user.getId());
-        if (sessions == null) {
-            sessions = new CopyOnWriteArrayList<>();
-            if (userSessionsMap.putIfAbsent(user.getId(), sessions) != null) {
-                sessions = userSessionsMap.get(user.getId());
-            }
-        }
-        sessions.add(session);
-    }
-
-    @Override
-    public void removeSession(WebSocketSession session) {
-        // 移除从 idSessions 中
-        idSessions.remove(session.getId());
-        // 移除从 idSessions 中
-        LoginUser user = WebSocketFrameworkUtils.getLoginUser(session);
-        if (user == null) {
-            return;
-        }
-        ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(user.getUserType());
-        if (userSessionsMap == null) {
-            return;
-        }
-        CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(user.getId());
-        sessions.removeIf(session0 -> session0.getId().equals(session.getId()));
-        if (CollUtil.isEmpty(sessions)) {
-            userSessionsMap.remove(user.getId(), sessions);
-        }
-    }
-
-    @Override
-    public WebSocketSession getSession(String id) {
-        return idSessions.get(id);
-    }
-
-    @Override
-    public Collection<WebSocketSession> getSessionList(Integer userType) {
-        ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(userType);
-        if (CollUtil.isEmpty(userSessionsMap)) {
-            return new ArrayList<>();
-        }
-        LinkedList<WebSocketSession> result = new LinkedList<>(); // 避免扩容
-        Long contextTenantId = TenantContextHolder.getTenantId();
-        for (List<WebSocketSession> sessions : userSessionsMap.values()) {
-            if (CollUtil.isEmpty(sessions)) {
-                continue;
-            }
-            // 特殊:如果租户不匹配,则直接排除
-            if (contextTenantId != null) {
-                Long userTenantId = WebSocketFrameworkUtils.getTenantId(sessions.get(0));
-                if (!contextTenantId.equals(userTenantId)) {
-                    continue;
-                }
-            }
-            result.addAll(sessions);
-        }
-        return result;
-    }
-
-    @Override
-    public Collection<WebSocketSession> getSessionList(Integer userType, Long userId) {
-        ConcurrentMap<Long, CopyOnWriteArrayList<WebSocketSession>> userSessionsMap = userSessions.get(userType);
-        if (CollUtil.isEmpty(userSessionsMap)) {
-            return new ArrayList<>();
-        }
-        CopyOnWriteArrayList<WebSocketSession> sessions = userSessionsMap.get(userId);
-        return CollUtil.isNotEmpty(sessions) ? new ArrayList<>(sessions) : new ArrayList<>();
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/util/WebSocketFrameworkUtils.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/util/WebSocketFrameworkUtils.java
deleted file mode 100644
index 96a6c45..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/core/util/WebSocketFrameworkUtils.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.iailab.framework.websocket.core.util;
-
-import com.iailab.framework.security.core.LoginUser;
-import org.springframework.web.socket.WebSocketSession;
-
-import java.util.Map;
-
-/**
- * 专属于 web 包的工具类
- *
- * @author iailab
- */
-public class WebSocketFrameworkUtils {
-
-    public static final String ATTRIBUTE_LOGIN_USER = "LOGIN_USER";
-
-    /**
-     * 设置当前用户
-     *
-     * @param loginUser 登录用户
-     * @param attributes Session
-     */
-    public static void setLoginUser(LoginUser loginUser, Map<String, Object> attributes) {
-        attributes.put(ATTRIBUTE_LOGIN_USER, loginUser);
-    }
-
-    /**
-     * 获取当前用户
-     *
-     * @return 当前用户
-     */
-    public static LoginUser getLoginUser(WebSocketSession session) {
-        return (LoginUser) session.getAttributes().get(ATTRIBUTE_LOGIN_USER);
-    }
-
-    /**
-     * 获得当前用户的编号
-     *
-     * @return 用户编号
-     */
-    public static Long getLoginUserId(WebSocketSession session) {
-        LoginUser loginUser = getLoginUser(session);
-        return loginUser != null ? loginUser.getId() : null;
-    }
-
-    /**
-     * 获得当前用户的类型
-     *
-     * @return 用户编号
-     */
-    public static Integer getLoginUserType(WebSocketSession session) {
-        LoginUser loginUser = getLoginUser(session);
-        return loginUser != null ? loginUser.getUserType() : null;
-    }
-
-    /**
-     * 获得当前用户的租户编号
-     *
-     * @param session Session
-     * @return 租户编号
-     */
-    public static Long getTenantId(WebSocketSession session) {
-        LoginUser loginUser = getLoginUser(session);
-        return loginUser != null ? loginUser.getTenantId() : null;
-    }
-
-}
diff --git a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/package-info.java b/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/package-info.java
deleted file mode 100644
index e10f7ce..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/java/com/iailab/framework/websocket/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * WebSocket 框架,支持多节点的广播
- */
-package com.iailab.framework.websocket;
diff --git a/iailab-framework/iailab-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/iailab-framework/iailab-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index 08c8131..0000000
--- a/iailab-framework/iailab-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1 +0,0 @@
-com.iailab.framework.websocket.config.IailabWebSocketAutoConfiguration
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/pom.xml b/iailab-framework/iailab-common/pom.xml
deleted file mode 100644
index ad63de0..0000000
--- a/iailab-framework/iailab-common/pom.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.iailab</groupId>
-        <artifactId>iailab-framework</artifactId>
-        <version>${revision}</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <artifactId>iailab-common</artifactId>
-    <packaging>jar</packaging>
-
-    <name>${project.artifactId}</name>
-    <description>定义基础 pojo 类、枚举、工具类等等</description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <dependencies>
-        <!-- Spring 核心 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-core</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-expression</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-aop</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-        <dependency>
-            <groupId>org.aspectj</groupId>
-            <artifactId>aspectjweaver</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <!-- 用于生成自定义的 Spring @ConfigurationProperties 配置类的说明文件 -->
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Web 相关 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>jakarta.servlet</groupId>
-            <artifactId>jakarta.servlet-api</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-ui</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <!-- 监控相关 -->
-        <dependency>
-            <groupId>org.apache.skywalking</groupId>
-            <artifactId>apm-toolkit-trace</artifactId>
-        </dependency>
-
-        <!-- 工具类相关 -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.mapstruct</groupId>
-            <artifactId>mapstruct</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.mapstruct</groupId>
-            <artifactId>mapstruct-jdk8</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
-        </dependency>
-        <dependency>
-            <groupId>org.mapstruct</groupId>
-            <artifactId>mapstruct-processor</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-core</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.datatype</groupId>
-            <artifactId>jackson-datatype-jsr310</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,只有工具类需要使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>jakarta.validation</groupId>
-            <artifactId>jakarta.validation-api</artifactId>
-<!--            <scope>provided</scope> &lt;!&ndash; 设置为 provided,主要是 PageParam 使用到 &ndash;&gt;-->
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>joda-time</groupId>
-            <artifactId>joda-time</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>transmittable-thread-local</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.jsoup</groupId>
-            <artifactId>jsoup</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
-            <artifactId>easy-trans-anno</artifactId> <!-- 默认引入的原因,方便 xxx-module-api 包使用 -->
-        </dependency>
-
-        <!-- Test 测试相关 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/iailab-framework/iailab-common/src/main/java/com/fhs/trans/service/AutoTransable.java b/iailab-framework/iailab-common/src/main/java/com/fhs/trans/service/AutoTransable.java
deleted file mode 100644
index b00d45e..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/fhs/trans/service/AutoTransable.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.fhs.trans.service;
-
-import com.fhs.core.trans.vo.VO;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 只有实现了这个接口的才能自动翻译
- *
- * 为什么要赋值粘贴到 iailab-common 包下?
- * 因为 AutoTransable 属于 easy-trans-service 下,无法方便的在 iailab-module-xxx-api 模块下使用
- *
- * @author jackwang
- * @since  2020-05-19 10:26:15
- */
-public interface AutoTransable<V extends VO> {
-
-    /**
-     * 根据 ids 查询数据列表
-     *
-     * 改方法已过期啦,请使用 selectByIds
-     *
-     * @param ids 编号数组
-     * @return 数据列表
-     */
-    @Deprecated
-    default List<V> findByIds(List<? extends Object> ids){
-        return new ArrayList<>();
-    }
-
-    /**
-     * 根据 ids 查询
-     *
-     * @param ids 编号数组
-     * @return 数据列表
-     */
-    default List<V> selectByIds(List<? extends Object> ids){
-        return this.findByIds(ids);
-    }
-
-    /**
-     * 获取 db 中所有的数据
-     *
-     * @return db 中所有的数据
-     */
-    default List<V> select(){
-        return new ArrayList<>();
-    }
-
-    /**
-     * 根据 id 获取 vo
-     *
-     * @param primaryValue id
-     * @return vo
-     */
-    V selectById(Object primaryValue);
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoBpm.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoBpm.java
deleted file mode 100644
index 33abe2f..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoBpm.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * 业务流程
- *
- * @author PanZhibao
- * @Description
- * @createTime 2022年12月20日 16:10:00
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface AutoBpm {
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoDict.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoDict.java
deleted file mode 100644
index 7205fb9..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoDict.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * @author PanZhibao
- * @Description
- * @createTime 2022年05月21日 10:59:00
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface AutoDict {
-
-    /**
-     * 暂时无用
-     * @return
-     */
-    String value() default "";
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoUser.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoUser.java
deleted file mode 100644
index c1c0a36..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/AutoUser.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * @author PanZhibao
- * @Description
- * @createTime 2023年06月07日 11:35:00
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface AutoUser {
-
-    /**
-     * 暂时无用
-     * @return
-     */
-    String value() default "";
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/BpmProcess.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/BpmProcess.java
deleted file mode 100644
index 8453bef..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/BpmProcess.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 业务流程ID
- *
- * @author PanZhibao
- * @Description
- * @createTime 2022年12月20日 16:17:00
- */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface BpmProcess {
-
-    /**
-     * 业务ID
-     *
-     * @return
-     */
-    String businessKey();
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/BpmStatus.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/BpmStatus.java
deleted file mode 100644
index 213f0a7..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/BpmStatus.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 业务流程状态
- *
- * @author PanZhibao
- * @Description
- * @createTime 2022年12月20日 16:14:00
- */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface BpmStatus {
-
-    /**
-     * 业务ID
-     *
-     * @return
-     */
-    String businessKey();
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/Dict.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/Dict.java
deleted file mode 100644
index dd01bb5..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/Dict.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 字典注解
- *
- * @author PanZhibao
- * @Description
- * @createTime 2022年05月20日 17:36:00
- */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Dict {
-
-    /**
-     * 数据code
-     *
-     * @return
-     */
-    String dicCode();
-
-    /**
-     * 数据itemValue
-     *
-     * @return
-     */
-    String itemValue();
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/UserRealName.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/UserRealName.java
deleted file mode 100644
index a142543..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/annotation/UserRealName.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.framework.common.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * @author PanZhibao
- * @Description
- * @createTime 2023年06月07日 11:37:00
- */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface UserRealName {
-
-    /**
-     * 用户ID
-     *
-     * @return
-     */
-    String userid() default "";
-
-    /**
-     * 用户账号
-     *
-     * @return
-     */
-    String username() default "";
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/CacheConstant.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/CacheConstant.java
deleted file mode 100644
index 36e9ba2..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/CacheConstant.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.iailab.framework.common.constant;
-
-/**
- * @author: huangxutao
- * @date: 2019-06-14
- * @description: 缓存常量
- */
-public interface CacheConstant {
-
-	/**
-	 * 字典信息缓存(含禁用的字典项)
-	 */
-    public static final String SYS_DICT_CACHE = "sys:cache:dict";
-
-	/**
-	 * 字典信息缓存 status为有效的
-	 */
-	public static final String SYS_ENABLE_DICT_CACHE = "sys:cache:dictEnable";
-	/**
-	 * 表字典信息缓存
-	 */
-    public static final String SYS_DICT_TABLE_CACHE = "sys:cache:dictTable";
-	public static final String SYS_DICT_TABLE_BY_KEYS_CACHE = SYS_DICT_TABLE_CACHE + "ByKeys";
-
-	/**
-	 * 数据权限配置缓存
-	 */
-    public static final String SYS_DATA_PERMISSIONS_CACHE = "sys:cache:permission:datarules";
-
-	/**
-	 * 缓存用户信息
-	 */
-	public static final String SYS_USERS_CACHE = "sys:cache:user";
-
-	/**
-	 * 全部部门信息缓存
-	 */
-	public static final String SYS_DEPARTS_CACHE = "sys:cache:depart:alldata";
-
-
-	/**
-	 * 全部部门ids缓存
-	 */
-	public static final String SYS_DEPART_IDS_CACHE = "sys:cache:depart:allids";
-
-
-	/**
-	 * 测试缓存key
-	 */
-	public static final String TEST_DEMO_CACHE = "test:demo";
-
-	/**
-	 * 字典信息缓存
-	 */
-	public static final String SYS_DYNAMICDB_CACHE = "sys:cache:dbconnect:dynamic:";
-
-	/**
-	 * gateway路由缓存
-	 */
-	public static final String GATEWAY_ROUTES = "sys:cache:cloud:gateway_routes";
-
-
-	/**
-	 * gatewayAPI缓存
-	 */
-	public static final String GATEWAY_APIS = "sys:cache:cloud:gateway_apis";
-
-	/**
-	 * gateway路由 reload key
-	 */
-	public static final String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
-
-	/**
-	 * TODO 冗余代码 待删除
-	 *插件商城排行榜
-	 */
-	public static final String PLUGIN_MALL_RANKING = "pluginMall::rankingList";
-	/**
-	 * TODO 冗余代码 待删除
-	 *插件商城排行榜
-	 */
-	public static final String PLUGIN_MALL_PAGE_LIST = "pluginMall::queryPageList";
-
-
-	/**
-	 * online列表页配置信息缓存key
-	 */
-	public static final String ONLINE_LIST = "sys:cache:online:list";
-
-	/**
-	 * online表单页配置信息缓存key
-	 */
-	public static final String ONLINE_FORM = "sys:cache:online:form";
-
-	/**
-	 * online报表
-	 */
-	public static final String ONLINE_RP = "sys:cache:online:rp";
-
-	/**
-	 * online图表
-	 */
-	public static final String ONLINE_GRAPH = "sys:cache:online:graph";
-	/**
-	 * 拖拽页面信息缓存
-	 */
-	public static final String DRAG_PAGE_CACHE = "drag:cache:param";
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/CommonConstant.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/CommonConstant.java
deleted file mode 100644
index 5fb8fca..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/CommonConstant.java
+++ /dev/null
@@ -1,406 +0,0 @@
-package com.iailab.framework.common.constant;
-
-import java.math.BigDecimal;
-
-/**
- * @Description: 通用常量
- */
-public interface CommonConstant {
-
-    BigDecimal BAD_VALUE = new BigDecimal("-2");
-
-    BigDecimal ZERO_VALUE = new BigDecimal("0");
-
-	/**
-	 * 正常状态
-	 */
-	public static final Integer STATUS_NORMAL = 0;
-
-	/**
-	 * 禁用状态
-	 */
-	public static final Integer STATUS_DISABLE = -1;
-
-	/**
-	 * 删除标志
-	 */
-	public static final Integer DEL_FLAG_1 = 1;
-
-	/**
-	 * 未删除
-	 */
-	public static final Integer DEL_FLAG_0 = 0;
-
-    /**
-     * 未提交
-     */
-    public static final Integer SUBMINT_STATUS_0 = 0;
-
-	/**
-	 * 系统日志类型: 登录
-	 */
-	public static final int LOG_TYPE_1 = 1;
-	
-	/**
-	 * 系统日志类型: 操作
-	 */
-	public static final int LOG_TYPE_2 = 2;
-
-	/**
-	 * 操作日志类型: 查询
-	 */
-	public static final int OPERATE_TYPE_1 = 1;
-	
-	/**
-	 * 操作日志类型: 添加
-	 */
-	public static final int OPERATE_TYPE_2 = 2;
-	
-	/**
-	 * 操作日志类型: 更新
-	 */
-	public static final int OPERATE_TYPE_3 = 3;
-	
-	/**
-	 * 操作日志类型: 删除
-	 */
-	public static final int OPERATE_TYPE_4 = 4;
-	
-	/**
-	 * 操作日志类型: 倒入
-	 */
-	public static final int OPERATE_TYPE_5 = 5;
-	
-	/**
-	 * 操作日志类型: 导出
-	 */
-	public static final int OPERATE_TYPE_6 = 6;
-
-    /**
-     * 提交
-     */
-    public static final int SUBMIT_FLAG_1 = 1;
-
-    /**
-     * 提交
-     */
-    public static final int SUBMIT_FLAG_0 = 0;
-
-    /**
-     * 启用
-     */
-    public static final int IS_ENABLE = 1;
-
-    /**
-     * 常量点类型
-     */
-    public static final String POINT_TYPE_NAME_CONSTANT = "CONSTANT";
-	
-	
-	/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
-    public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
-    /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
-    public static final Integer SC_OK_200 = 200;
-    
-    /**访问权限认证未通过 510*/
-    public static final Integer SC_JEECG_NO_AUTHZ=510;
-
-    /** 登录用户Shiro权限缓存KEY前缀 */
-    public static String PREFIX_USER_SHIRO_CACHE  = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:";
-    /** 登录用户Token令牌缓存KEY前缀 */
-    public static final String PREFIX_USER_TOKEN  = "prefix_user_token_";
-//    /** Token缓存时间:3600秒即一小时 */
-//    public static final int  TOKEN_EXPIRE_TIME  = 3600;
-
-    /** 登录二维码 */
-    public static final String  LOGIN_QRCODE_PRE  = "QRCODELOGIN:";
-    public static final String  LOGIN_QRCODE  = "LQ:";
-    /** 登录二维码token */
-    public static final String  LOGIN_QRCODE_TOKEN  = "LQT:";
-
-
-    /**
-     *  0:一级菜单
-     */
-    public static final Integer MENU_TYPE_0  = 0;
-   /**
-    *  1:子菜单 
-    */
-    public static final Integer MENU_TYPE_1  = 1;
-    /**
-     *  2:按钮权限
-     */
-    public static final Integer MENU_TYPE_2  = 2;
-
-    /**通告对象类型(USER:指定用户,ALL:全体用户)*/
-    public static final String MSG_TYPE_UESR  = "USER";
-    public static final String MSG_TYPE_ALL  = "ALL";
-    
-    /**发布状态(0未发布,1已发布,2已撤销)*/
-    public static final String NO_SEND  = "0";
-    public static final String HAS_SEND  = "1";
-    public static final String HAS_CANCLE  = "2";
-    
-    /**阅读状态(0未读,1已读)*/
-    public static final String HAS_READ_FLAG  = "1";
-    public static final String NO_READ_FLAG  = "0";
-    
-    /**优先级(L低,M中,H高)*/
-    public static final String PRIORITY_L  = "L";
-    public static final String PRIORITY_M  = "M";
-    public static final String PRIORITY_H  = "H";
-    
-    /**
-     * 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板
-     */
-    public static final String SMS_TPL_TYPE_0  = "0";
-    public static final String SMS_TPL_TYPE_1  = "1";
-    public static final String SMS_TPL_TYPE_2  = "2";
-    
-    /**
-     * 状态(0无效1有效)
-     */
-    public static final String STATUS_0 = "0";
-    public static final String STATUS_1 = "1";
-    
-    /**
-     * 同步工作流引擎1同步0不同步
-     */
-    public static final Integer ACT_SYNC_1 = 1;
-    public static final Integer ACT_SYNC_0 = 0;
-
-    /**
-     * 消息类型1:通知公告2:系统消息
-     */
-    public static final String MSG_CATEGORY_1 = "1";
-    public static final String MSG_CATEGORY_2 = "2";
-    
-    /**
-     * 是否配置菜单的数据权限 1是0否
-     */
-    public static final Integer RULE_FLAG_0 = 0;
-    public static final Integer RULE_FLAG_1 = 1;
-
-    /**
-     * 是否用户已被冻结 1正常(解冻) 2冻结
-     */
-    public static final Integer USER_UNFREEZE = 1;
-    public static final Integer USER_FREEZE = 2;
-    
-    /**字典翻译文本后缀*/
-    public static final String DICT_TEXT_SUFFIX = "_dictText";
-
-    /**
-     * 表单设计器主表类型
-     */
-    public static final Integer DESIGN_FORM_TYPE_MAIN = 1;
-
-    /**
-     * 表单设计器子表表类型
-     */
-    public static final Integer DESIGN_FORM_TYPE_SUB = 2;
-
-    /**
-     * 表单设计器URL授权通过
-     */
-    public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1;
-
-    /**
-     * 表单设计器URL授权未通过
-     */
-    public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;
-
-    /**
-     * 表单设计器新增 Flag
-     */
-    public static final String DESIGN_FORM_URL_TYPE_ADD = "add";
-    /**
-     * 表单设计器修改 Flag
-     */
-    public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit";
-    /**
-     * 表单设计器详情 Flag
-     */
-    public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail";
-    /**
-     * 表单设计器复用数据 Flag
-     */
-    public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse";
-    /**
-     * 表单设计器编辑 Flag (已弃用)
-     */
-    public static final String DESIGN_FORM_URL_TYPE_VIEW = "view";
-
-    /**
-     * online参数值设置(是:Y, 否:N)
-     */
-    public static final String ONLINE_PARAM_VAL_IS_TURE = "Y";
-    public static final String ONLINE_PARAM_VAL_IS_FALSE = "N";
-
-    /**
-     * 文件上传类型(本地:local,Minio:minio,阿里云:alioss)
-     */
-    public static final String UPLOAD_TYPE_LOCAL = "local";
-    public static final String UPLOAD_TYPE_MINIO = "minio";
-    public static final String UPLOAD_TYPE_OSS = "alioss";
-
-    /**
-     * 文档上传自定义桶名称
-     */
-    public static final String UPLOAD_CUSTOM_BUCKET = "eoafile";
-    /**
-     * 文档上传自定义路径
-     */
-    public static final String UPLOAD_CUSTOM_PATH = "eoafile";
-    /**
-     * 文件外链接有效天数
-     */
-    public static final Integer UPLOAD_EFFECTIVE_DAYS = 1;
-
-    /**
-     * 员工身份 (1:普通员工  2:上级)
-     */
-    public static final Integer USER_IDENTITY_1 = 1;
-    public static final Integer USER_IDENTITY_2 = 2;
-
-    /** sys_user 表 username 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username";
-    /** sys_user 表 work_no 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no";
-    /** sys_user 表 phone 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone";
-    /** 达梦数据库升提示。违反表[SYS_USER]唯一性约束 */
-    public static final String SQL_INDEX_UNIQ_SYS_USER = "唯一性约束";
-
-    /** sys_user 表 email 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email";
-    /** sys_quartz_job 表 job_class_name 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name";
-    /** sys_position 表 code 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_CODE = "uniq_code";
-    /** sys_role 表 code 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code";
-    /** sys_depart 表 code 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code";
-    /** sys_category 表 code 唯一键索引 */
-    public static final String SQL_INDEX_UNIQ_CATEGORY_CODE = "idx_sc_code";
-    /**
-     * 在线聊天 是否为默认分组
-     */
-    public static final String IM_DEFAULT_GROUP = "1";
-    /**
-     * 在线聊天 图片文件保存路径
-     */
-    public static final String IM_UPLOAD_CUSTOM_PATH = "imfile";
-    /**
-     * 在线聊天 用户状态
-     */
-    public static final String IM_STATUS_ONLINE = "online";
-
-    /**
-     * 在线聊天 SOCKET消息类型
-     */
-    public static final String IM_SOCKET_TYPE = "chatMessage";
-
-    /**
-     * 在线聊天 是否开启默认添加好友 1是 0否
-     */
-    public static final String IM_DEFAULT_ADD_FRIEND = "1";
-
-    /**
-     * 在线聊天 用户好友缓存前缀
-     */
-    public static final String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_";
-
-    /**
-     * 考勤补卡业务状态 (1:同意  2:不同意)
-     */
-    public static final String SIGN_PATCH_BIZ_STATUS_1 = "1";
-    public static final String SIGN_PATCH_BIZ_STATUS_2 = "2";
-
-    /**
-     * 公文文档上传自定义路径
-     */
-    public static final String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc";
-     /**
-     * 公文文档下载自定义路径
-     */
-    public static final String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown";
-
-    /**
-     * WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板))
-     */
-    public static final String WPS_TYPE_1="1";
-    public static final String WPS_TYPE_2="2";
-
-
-    public final static String X_ACCESS_TOKEN = "X-Access-Token";
-    public final static String X_SIGN = "X-Sign";
-    public final static String X_TIMESTAMP = "X-TIMESTAMP";
-    public final static String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!";
-
-    /**
-     * 多租户 请求头
-     */
-    public final static String TENANT_ID = "tenant-id";
-
-    /**
-     * 微服务读取配置文件属性 服务地址
-     */
-    public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr";
-
-    /**
-     * 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用
-     */
-    public final static String THIRD_LOGIN_CODE = "third_login_code";
-
-    /**
-     * 第三方APP同步方向:本地 --> 第三方APP
-     */
-    String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
-    /**
-     * 第三方APP同步方向:第三方APP --> 本地
-     */
-    String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
-
-    /** 系统通告消息状态:0=未发布 */
-    String ANNOUNCEMENT_SEND_STATUS_0 = "0";
-    /** 系统通告消息状态:1=已发布 */
-    String ANNOUNCEMENT_SEND_STATUS_1 = "1";
-    /** 系统通告消息状态:2=已撤销 */
-    String ANNOUNCEMENT_SEND_STATUS_2 = "2";
-
-    /**ONLINE 报表权限用 从request中获取地址栏后的参数*/
-    String ONL_REP_URL_PARAM_STR="onlRepUrlParamStr";
-
-    /**POST请求*/
-    String HTTP_POST = "POST";
-
-    /**PUT请求*/
-    String HTTP_PUT = "PUT";
-
-    /**PATCH请求*/
-    String HTTP_PATCH = "PATCH";
-
-    /**未知的*/
-    String UNKNOWN = "unknown";
-
-    /**字符串http*/
-    String STR_HTTP = "http";
-
-    /**String 类型的空值*/
-    String STRING_NULL = "null";
-
-    /**java.util.Date 包*/
-    String JAVA_UTIL_DATE = "java.util.Date";
-
-    /**.do*/
-    String SPOT_DO = ".do";
-
-
-    /**前端vue版本标识*/
-    String VERSION="X-Version";
-
-    /**前端vue版本*/
-    String VERSION_VUE3="vue3";
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/Constant.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/Constant.java
deleted file mode 100644
index 0d530d5..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/Constant.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.constant;
-
-/**
- * 常量
- *
- * @author Mark sunlightcs@gmail.com
- */
-public interface Constant {
-    /**
-     * 成功
-     */
-    int SUCCESS = 1;
-    /**
-     * 失败
-     */
-    int FAIL = 0;
-    /**
-     * 菜单根节点标识
-     */
-    Long MENU_ROOT = 0L;
-    /**
-     * 部门根节点标识
-     */
-    Long DEPT_ROOT = 0L;
-    /**
-     *  升序
-     */
-    String ASC = "asc";
-    /**
-     * 降序
-     */
-    String DESC = "desc";
-    /**
-     * 创建时间字段名
-     */
-    String CREATE_DATE = "create_date";
-
-    String CREATE_TIME = "create_time";
-
-    /**
-     * 数据权限过滤
-     */
-    String SQL_FILTER = "sqlFilter";
-    /**
-     * 当前页码
-     */
-    String PAGE = "page";
-    /**
-     * 每页显示记录数
-     */
-    String LIMIT = "limit";
-    /**
-     * 排序字段
-     */
-    String ORDER_FIELD = "orderField";
-    /**
-     * 排序方式
-     */
-    String ORDER = "order";
-    /**
-     * token header
-     */
-    String TOKEN_HEADER = "authorization";
-
-    /**
-     * tenantCode
-     */
-    String TENANT_CODE = "tenantCode";
-
-    /**
-     * tenantId
-     */
-    String TENANT_ID = "tenantId";
-
-    /**
-     * tenantId
-     */
-    String HEAD_TENANT_ID = "tenant-id";
-
-    /**
-     * 云存储配置KEY
-     */
-    String CLOUD_STORAGE_CONFIG_KEY = "CLOUD_STORAGE_CONFIG_KEY";
-
-    Integer DEL_FLAG_0 = 0;
-
-    enum EnableStatus {
-        DISABLED(0),
-        NORMAL(1);
-
-        private int value;
-
-        private EnableStatus(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return this.value;
-        }
-    }
-
-    /**
-     * 定时任务状态
-     */
-    enum ScheduleStatus {
-        /**
-         * 暂停
-         */
-        PAUSE(0),
-        /**
-         * 正常
-         */
-        NORMAL(1);
-
-        private int value;
-
-        ScheduleStatus(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return value;
-        }
-    }
-
-    /**
-     * 云服务商
-     */
-    enum CloudService {
-        /**
-         * 七牛云
-         */
-        QINIU(1),
-        /**
-         * 阿里云
-         */
-        ALIYUN(2),
-        /**
-         * 腾讯云
-         */
-        QCLOUD(3);
-
-        private int value;
-
-        CloudService(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return value;
-        }
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/GlobalConstants.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/GlobalConstants.java
deleted file mode 100644
index 52bdc03..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/constant/GlobalConstants.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.iailab.framework.common.constant;
-
-/**
-* @Description: GlobalConstants
-* @author: scott
-* @date: 2020/01/01 16:01
-*/
-public class GlobalConstants {
-
-    /**
-     * 业务处理器beanName传递参数
-     */
-    public static final String HANDLER_NAME = "handlerName";
-
-    /**
-     * 路由刷新触发器
-     */
-    public static final String LODER_ROUDER_HANDLER = "loderRouderHandler";
-
-    /**
-     * API刷新触发器
-     */
-    public static final String LODER_API_HANDLER = "loderApiHandler";
-
-    /**
-     * redis消息通道名称
-     */
-    public static final String REDIS_TOPIC_NAME="redis_topic";
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/IntArrayValuable.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/IntArrayValuable.java
deleted file mode 100644
index a4ff210..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/IntArrayValuable.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.iailab.framework.common.core;
-
-/**
- * 可生成 Int 数组的接口
- *
- * @author iailab
- */
-public interface IntArrayValuable {
-
-    /**
-     * @return int 数组
-     */
-    int[] array();
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/KeyValue.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/KeyValue.java
deleted file mode 100644
index a0e885c..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/KeyValue.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.iailab.framework.common.core;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * Key Value 的键值对
- *
- * @author iailab
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class KeyValue<K, V> implements Serializable {
-
-    private K key;
-    private V value;
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/dto/TreeLabelDTO.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/dto/TreeLabelDTO.java
deleted file mode 100644
index cfa0e22..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/dto/TreeLabelDTO.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.iailab.framework.common.dto;
-
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * @author PanZhibao
- * @Description
- * @createTime 2024年09月23日
- */
-@Data
-public class TreeLabelDTO {
-
-    private String value;
-
-    private String label;
-
-    private List<TreeLabelDTO> children;
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/CommonStatusEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/CommonStatusEnum.java
deleted file mode 100644
index a611b8b..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/CommonStatusEnum.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.common.enums;
-
-import cn.hutool.core.util.ObjUtil;
-import com.iailab.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * 通用状态枚举
- *
- * @author iailab
- */
-@Getter
-@AllArgsConstructor
-public enum CommonStatusEnum implements IntArrayValuable {
-
-    ENABLE(0, "开启"),
-    DISABLE(1, "关闭");
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray();
-
-    /**
-     * 状态值
-     */
-    private final Integer status;
-    /**
-     * 状态名
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-    public static boolean isEnable(Integer status) {
-        return ObjUtil.equal(ENABLE.status, status);
-    }
-
-    public static boolean isDisable(Integer status) {
-        return ObjUtil.equal(DISABLE.status, status);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DateIntervalEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DateIntervalEnum.java
deleted file mode 100644
index af55211..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DateIntervalEnum.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.common.enums;
-
-import cn.hutool.core.util.ArrayUtil;
-import com.iailab.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * 时间间隔的枚举
- *
- * @author dhb52
- */
-@Getter
-@AllArgsConstructor
-public enum DateIntervalEnum implements IntArrayValuable {
-
-    DAY(1, "天"),
-    WEEK(2, "周"),
-    MONTH(3, "月"),
-    QUARTER(4, "季度"),
-    YEAR(5, "年")
-    ;
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DateIntervalEnum::getInterval).toArray();
-
-    /**
-     * 类型
-     */
-    private final Integer interval;
-    /**
-     * 名称
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-    public static DateIntervalEnum valueOf(Integer interval) {
-        return ArrayUtil.firstMatch(item -> item.getInterval().equals(interval), DateIntervalEnum.values());
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DocumentEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DocumentEnum.java
deleted file mode 100644
index 01f8ef4..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/DocumentEnum.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.framework.common.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 文档地址
- *
- * @author iailab
- */
-@Getter
-@AllArgsConstructor
-public enum DocumentEnum {
-
-    REDIS_INSTALL("https://iailab.cn", "Redis 安装文档"),
-    TENANT("https://iailab.cn", "SaaS 多租户文档");
-    
-    private final String url;
-    private final String memo;
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/ErrorCode.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/ErrorCode.java
deleted file mode 100644
index 6228b18..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/ErrorCode.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.enums;
-
-/**
- * 错误编码,由5位数字组成,前2位为模块编码,后3位为业务编码
- * <p>
- * 如:10001(10代表系统模块,001代表业务代码)
- * </p>
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-public interface ErrorCode {
-    int INTERNAL_SERVER_ERROR = 500;
-    int UNAUTHORIZED = 401;
-
-    int NOT_NULL = 10001;
-    int DB_RECORD_EXISTS = 10002;
-    int PARAMS_GET_ERROR = 10003;
-    int ACCOUNT_PASSWORD_ERROR = 10004;
-    int ACCOUNT_DISABLE = 10005;
-    int IDENTIFIER_NOT_NULL = 10006;
-    int CAPTCHA_ERROR = 10007;
-    int SUB_MENU_EXIST = 10008;
-    int PASSWORD_ERROR = 10009;
-    int SUPERIOR_DEPT_ERROR = 10011;
-    int SUPERIOR_MENU_ERROR = 10012;
-    int DATA_SCOPE_PARAMS_ERROR = 10013;
-    int DEPT_SUB_DELETE_ERROR = 10014;
-    int DEPT_USER_DELETE_ERROR = 10015;
-    int UPLOAD_FILE_EMPTY = 10019;
-    int TOKEN_NOT_EMPTY = 10020;
-    int TOKEN_INVALID = 10021;
-    int ACCOUNT_LOCK = 10022;
-    int OSS_UPLOAD_FILE_ERROR = 10024;
-    int REDIS_ERROR = 10027;
-    int JOB_ERROR = 10028;
-    int INVALID_SYMBOL = 10029;
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/RpcConstants.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/RpcConstants.java
deleted file mode 100644
index b29ee71..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/RpcConstants.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.iailab.framework.common.enums;
-
-/**
- * RPC 相关的枚举
- *
- * 虽然放在 iailab-common-rpc 会相对合适,但是每个 API 模块需要使用到,所以暂时只好放在此处
- *
- * @author iailab
- */
-public class RpcConstants {
-
-    /**
-     * RPC API 的前缀
-     */
-    public static final String RPC_API_PREFIX = "/rpc-api";
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/TerminalEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/TerminalEnum.java
deleted file mode 100644
index c49ae51..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/TerminalEnum.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.framework.common.enums;
-
-import com.iailab.framework.common.core.IntArrayValuable;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-import java.util.Arrays;
-
-/**
- * 终端的枚举
- *
- * @author iailab
- */
-@RequiredArgsConstructor
-@Getter
-public enum TerminalEnum implements IntArrayValuable {
-
-    UNKNOWN(0, "未知"), // 目的:在无法解析到 terminal 时,使用它
-    WECHAT_MINI_PROGRAM(10, "微信小程序"),
-    WECHAT_WAP(11, "微信公众号"),
-    H5(20, "H5 网页"),
-    APP(31, "手机 App"),
-    ;
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray();
-
-    /**
-     * 终端
-     */
-    private final Integer terminal;
-    /**
-     * 终端名
-     */
-    private final String name;
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/UserTypeEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/UserTypeEnum.java
deleted file mode 100644
index 560e02c..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/UserTypeEnum.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.framework.common.enums;
-
-import cn.hutool.core.util.ArrayUtil;
-import com.iailab.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * 全局用户类型枚举
- */
-@AllArgsConstructor
-@Getter
-public enum UserTypeEnum implements IntArrayValuable {
-
-    MEMBER(1, "会员"), // 面向 c 端,普通用户
-    ADMIN(2, "管理员"); // 面向 b 端,管理后台
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();
-
-    /**
-     * 类型
-     */
-    private final Integer value;
-    /**
-     * 类型名
-     */
-    private final String name;
-
-    public static UserTypeEnum valueOf(Integer value) {
-        return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values());
-    }
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/WebFilterOrderEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/WebFilterOrderEnum.java
deleted file mode 100644
index ea7e7f7..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/enums/WebFilterOrderEnum.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.common.enums;
-
-/**
- * Web 过滤器顺序的枚举类,保证过滤器按照符合我们的预期
- *
- *  考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 enum 包下
- *
- * @author iailab
- */
-public interface WebFilterOrderEnum {
-
-    int CORS_FILTER = Integer.MIN_VALUE;
-
-    int TRACE_FILTER = CORS_FILTER + 1;
-
-    int ENV_TAG_FILTER = TRACE_FILTER + 1;
-
-    int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500;
-
-    // OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等
-
-    int TENANT_CONTEXT_FILTER = - 104; // 需要保证在 ApiAccessLogFilter 前面
-
-    int API_ACCESS_LOG_FILTER = -103; // 需要保证在 RequestBodyCacheFilter 后面
-
-    int XSS_FILTER = -102;  // 需要保证在 RequestBodyCacheFilter 后面
-
-    // Spring Security Filter 默认为 -100,可见 org.springframework.boot.autoconfigure.security.SecurityProperties 配置属性类
-
-    int TENANT_SECURITY_FILTER = -99; // 需要保证在 Spring Security 过滤器后面
-
-    int FLOWABLE_FILTER = -98; // 需要保证在 Spring Security 过滤后面
-
-    int DEMO_FILTER = Integer.MAX_VALUE;
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ErrorCode.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ErrorCode.java
deleted file mode 100644
index af64f8f..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ErrorCode.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.iailab.framework.common.exception;
-
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.iailab.framework.common.exception.enums.ServiceErrorCodeRange;
-import lombok.Data;
-
-/**
- * 错误码对象
- *
- * 全局错误码,占用 [0, 999], 参见 {@link GlobalErrorCodeConstants}
- * 业务异常错误码,占用 [1 000 000 000, +∞),参见 {@link ServiceErrorCodeRange}
- *
- * TODO 错误码设计成对象的原因,为未来的 i18 国际化做准备
- */
-@Data
-public class ErrorCode {
-
-    /**
-     * 错误码
-     */
-    private final Integer code;
-    /**
-     * 错误提示
-     */
-    private final String msg;
-
-    public ErrorCode(Integer code, String message) {
-        this.code = code;
-        this.msg = message;
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ExceptionUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ExceptionUtils.java
deleted file mode 100644
index b4bd8e0..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ExceptionUtils.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.exception;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * Exception工具类
- *
- * @author Mark sunlightcs@gmail.com
- */
-public class ExceptionUtils {
-
-    /**
-     * 获取异常信息
-     * @param ex  异常
-     * @return    返回异常信息
-     */
-    public static String getErrorStackTrace(Exception ex){
-        StringWriter sw = null;
-        PrintWriter pw = null;
-        try {
-            sw = new StringWriter();
-            pw = new PrintWriter(sw, true);
-            ex.printStackTrace(pw);
-        }finally {
-            try {
-                if(pw != null) {
-                    pw.close();
-                }
-            } catch (Exception e) {
-
-            }
-            try {
-                if(sw != null) {
-                    sw.close();
-                }
-            } catch (IOException e) {
-
-            }
-        }
-
-        return sw.toString();
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ServerException.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ServerException.java
deleted file mode 100644
index 9e7f0f4..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ServerException.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.framework.common.exception;
-
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 服务器异常 Exception
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public final class ServerException extends RuntimeException {
-
-    /**
-     * 全局错误码
-     *
-     * @see GlobalErrorCodeConstants
-     */
-    private Integer code;
-    /**
-     * 错误提示
-     */
-    private String message;
-
-    /**
-     * 空构造方法,避免反序列化问题
-     */
-    public ServerException() {
-    }
-
-    public ServerException(ErrorCode errorCode) {
-        this.code = errorCode.getCode();
-        this.message = errorCode.getMsg();
-    }
-
-    public ServerException(Integer code, String message) {
-        this.code = code;
-        this.message = message;
-    }
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public ServerException setCode(Integer code) {
-        this.code = code;
-        return this;
-    }
-
-    @Override
-    public String getMessage() {
-        return message;
-    }
-
-    public ServerException setMessage(String message) {
-        this.message = message;
-        return this;
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ServiceException.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ServiceException.java
deleted file mode 100644
index 536bb40..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/ServiceException.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.framework.common.exception;
-
-import com.iailab.framework.common.exception.enums.ServiceErrorCodeRange;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 业务逻辑异常 Exception
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public final class ServiceException extends RuntimeException {
-
-    /**
-     * 业务错误码
-     *
-     * @see ServiceErrorCodeRange
-     */
-    private Integer code;
-    /**
-     * 错误提示
-     */
-    private String message;
-
-    /**
-     * 空构造方法,避免反序列化问题
-     */
-    public ServiceException() {
-    }
-
-    public ServiceException(ErrorCode errorCode) {
-        this.code = errorCode.getCode();
-        this.message = errorCode.getMsg();
-    }
-
-    public ServiceException(Integer code, String message) {
-        this.code = code;
-        this.message = message;
-    }
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public ServiceException setCode(Integer code) {
-        this.code = code;
-        return this;
-    }
-
-    @Override
-    public String getMessage() {
-        return message;
-    }
-
-    public ServiceException setMessage(String message) {
-        this.message = message;
-        return this;
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/enums/GlobalErrorCodeConstants.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/enums/GlobalErrorCodeConstants.java
deleted file mode 100644
index bf1e415..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/enums/GlobalErrorCodeConstants.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.framework.common.exception.enums;
-
-import com.iailab.framework.common.exception.ErrorCode;
-
-/**
- * 全局错误码枚举
- * 0-999 系统异常编码保留
- *
- * 一般情况下,使用 HTTP 响应状态码 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
- * 虽然说,HTTP 响应状态码作为业务使用表达能力偏弱,但是使用在系统层面还是非常不错的
- * 比较特殊的是,因为之前一直使用 0 作为成功,就不使用 200 啦。
- *
- * @author iailab
- */
-public interface GlobalErrorCodeConstants {
-
-    ErrorCode SUCCESS = new ErrorCode(0, "成功");
-
-    // ========== 客户端错误段 ==========
-
-    ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确");
-    ErrorCode UNAUTHORIZED = new ErrorCode(401, "账号未登录");
-    ErrorCode FORBIDDEN = new ErrorCode(403, "没有该操作权限");
-    ErrorCode NOT_FOUND = new ErrorCode(404, "请求未找到");
-    ErrorCode METHOD_NOT_ALLOWED = new ErrorCode(405, "请求方法不正确");
-    ErrorCode DATA_REPETITION = new ErrorCode(406, "数据库存在重复数据");
-    ErrorCode LOCKED = new ErrorCode(423, "请求失败,请稍后重试"); // 并发请求,不允许
-    ErrorCode TOO_MANY_REQUESTS = new ErrorCode(429, "请求过于频繁,请稍后重试");
-
-    // ========== 服务端错误段 ==========
-
-    ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");
-    ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启");
-    ErrorCode ERROR_CONFIGURATION = new ErrorCode(502, "错误的配置项");
-
-    // ========== 自定义错误段 ==========
-    ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求
-    ErrorCode DEMO_DENY = new ErrorCode(901, "演示模式,禁止写操作");
-
-    ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/enums/ServiceErrorCodeRange.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/enums/ServiceErrorCodeRange.java
deleted file mode 100644
index 237b926..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/enums/ServiceErrorCodeRange.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.framework.common.exception.enums;
-
-/**
- * 业务异常的错误码区间,解决:解决各模块错误码定义,避免重复,在此只声明不做实际使用
- *
- * 一共 10 位,分成四段
- *
- * 第一段,1 位,类型
- *      1 - 业务级别异常
- *      x - 预留
- * 第二段,3 位,系统类型
- *      001 - 用户系统
- *      002 - 商品系统
- *      003 - 订单系统
- *      004 - 支付系统
- *      005 - 优惠劵系统
- *      ... - ...
- * 第三段,3 位,模块
- *      不限制规则。
- *      一般建议,每个系统里面,可能有多个模块,可以再去做分段。以用户系统为例子:
- *          001 - OAuth2 模块
- *          002 - User 模块
- *          003 - MobileCode 模块
- * 第四段,3 位,错误码
- *       不限制规则。
- *       一般建议,每个模块自增。
- *
- * @author iailab
- */
-public class ServiceErrorCodeRange {
-
-    // 模块 infra 错误码区间 [1-001-000-000 ~ 1-002-000-000)
-    // 模块 system 错误码区间 [1-002-000-000 ~ 1-003-000-000)
-    // 模块 report 错误码区间 [1-003-000-000 ~ 1-004-000-000)
-    // 模块 member 错误码区间 [1-004-000-000 ~ 1-005-000-000)
-    // 模块 mp 错误码区间 [1-006-000-000 ~ 1-007-000-000)
-    // 模块 pay 错误码区间 [1-007-000-000 ~ 1-008-000-000)
-    // 模块 bpm 错误码区间 [1-009-000-000 ~ 1-010-000-000)
-
-    // 模块 product 错误码区间 [1-008-000-000 ~ 1-009-000-000)
-    // 模块 trade 错误码区间 [1-011-000-000 ~ 1-012-000-000)
-    // 模块 promotion 错误码区间 [1-013-000-000 ~ 1-014-000-000)
-
-    // 模块 crm 错误码区间 [1-020-000-000 ~ 1-021-000-000)
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/util/ServiceExceptionUtil.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/util/ServiceExceptionUtil.java
deleted file mode 100644
index da298fb..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/exception/util/ServiceExceptionUtil.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.iailab.framework.common.exception.util;
-
-import com.iailab.framework.common.exception.ErrorCode;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.google.common.annotations.VisibleForTesting;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * {@link ServiceException} 工具类
- *
- * 目的在于,格式化异常信息提示。
- * 考虑到 String.format 在参数不正确时会报错,因此使用 {} 作为占位符,并使用 {@link #doFormat(int, String, Object...)} 方法来格式化
- *
- */
-@Slf4j
-public class ServiceExceptionUtil {
-
-    // ========== 和 ServiceException 的集成 ==========
-
-    public static ServiceException exception(ErrorCode errorCode) {
-        return exception0(errorCode.getCode(), errorCode.getMsg());
-    }
-
-    public static ServiceException exception(ErrorCode errorCode, Object... params) {
-        return exception0(errorCode.getCode(), errorCode.getMsg(), params);
-    }
-
-    public static ServiceException exception0(Integer code, String messagePattern, Object... params) {
-        String message = doFormat(code, messagePattern, params);
-        return new ServiceException(code, message);
-    }
-
-    public static ServiceException invalidParamException(String messagePattern, Object... params) {
-        return exception0(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), messagePattern, params);
-    }
-
-    // ========== 格式化方法 ==========
-
-    /**
-     * 将错误编号对应的消息使用 params 进行格式化。
-     *
-     * @param code           错误编号
-     * @param messagePattern 消息模版
-     * @param params         参数
-     * @return 格式化后的提示
-     */
-    @VisibleForTesting
-    public static String doFormat(int code, String messagePattern, Object... params) {
-        StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50);
-        int i = 0;
-        int j;
-        int l;
-        for (l = 0; l < params.length; l++) {
-            j = messagePattern.indexOf("{}", i);
-            if (j == -1) {
-                log.error("[doFormat][参数过多:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
-                if (i == 0) {
-                    return messagePattern;
-                } else {
-                    sbuf.append(messagePattern.substring(i));
-                    return sbuf.toString();
-                }
-            } else {
-                sbuf.append(messagePattern, i, j);
-                sbuf.append(params[l]);
-                i = j + 2;
-            }
-        }
-        if (messagePattern.indexOf("{}", i) != -1) {
-            log.error("[doFormat][参数过少:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
-        }
-        sbuf.append(messagePattern.substring(i));
-        return sbuf.toString();
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/package-info.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/package-info.java
deleted file mode 100644
index 6c99aa5..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 基础的通用类,和框架无关
- *
- * 例如说,CommonResult 为通用返回
- */
-package com.iailab.framework.common;
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/CommonResult.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/CommonResult.java
deleted file mode 100644
index 147e44d..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/CommonResult.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package com.iailab.framework.common.pojo;
-
-import cn.hutool.core.lang.Assert;
-import com.iailab.framework.common.exception.ErrorCode;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.exception.enums.GlobalErrorCodeConstants;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.iailab.framework.common.exception.util.ServiceExceptionUtil;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-/**
- * 通用返回
- *
- * @param <T> 数据泛型
- */
-@Data
-public class CommonResult<T> implements Serializable {
-
-    /**
-     * 错误码
-     *
-     * @see ErrorCode#getCode()
-     */
-    private Integer code;
-    /**
-     * 返回数据
-     */
-    private T data;
-    /**
-     * 错误提示,用户可阅读
-     *
-     * @see ErrorCode#getMsg() ()
-     */
-    private String msg;
-
-    /**
-     * 将传入的 result 对象,转换成另外一个泛型结果的对象
-     *
-     * 因为 A 方法返回的 CommonResult 对象,不满足调用其的 B 方法的返回,所以需要进行转换。
-     *
-     * @param result 传入的 result 对象
-     * @param <T> 返回的泛型
-     * @return 新的 CommonResult 对象
-     */
-    public static <T> CommonResult<T> error(CommonResult<?> result) {
-        return error(result.getCode(), result.getMsg());
-    }
-
-    public static <T> CommonResult<T> error(Integer code, String message) {
-        cn.hutool.core.lang.Assert.notEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), code, "code 必须是错误的!");
-        CommonResult<T> result = new CommonResult<>();
-        result.code = code;
-        result.msg = message;
-        return result;
-    }
-
-    public static <T> CommonResult<T> error(ErrorCode errorCode, Object... params) {
-        Assert.notEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), errorCode.getCode(), "code 必须是错误的!");
-        CommonResult<T> result = new CommonResult<>();
-        result.code = errorCode.getCode();
-        result.msg = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), params);
-        return result;
-    }
-
-    public static <T> CommonResult<T> error(ErrorCode errorCode) {
-        return error(errorCode.getCode(), errorCode.getMsg());
-    }
-
-    public static <T> CommonResult<T> success(T data) {
-        CommonResult<T> result = new CommonResult<>();
-        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
-        result.data = data;
-        result.msg = "";
-        return result;
-    }
-
-    public static CommonResult<String> success() {
-        CommonResult<String> result = new CommonResult<>();
-        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
-        result.msg = "success";
-        return result;
-    }
-
-    public static boolean isSuccess(Integer code) {
-        return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode());
-    }
-
-    @JsonIgnore // 避免 jackson 序列化
-    public boolean isSuccess() {
-        return isSuccess(code);
-    }
-
-    @JsonIgnore // 避免 jackson 序列化
-    public boolean isError() {
-        return !isSuccess();
-    }
-
-    // ========= 和 Exception 异常体系集成 =========
-
-    /**
-     * 判断是否有异常。如果有,则抛出 {@link ServiceException} 异常
-     */
-    public void checkError() throws ServiceException {
-        if (isSuccess()) {
-            return;
-        }
-        // 业务异常
-        throw new ServiceException(code, msg);
-    }
-
-    /**
-     * 判断是否有异常。如果有,则抛出 {@link ServiceException} 异常
-     * 如果没有,则返回 {@link #data} 数据
-     */
-    @JsonIgnore // 避免 jackson 序列化
-    public T getCheckedData() {
-        checkError();
-        return data;
-    }
-
-    public static <T> CommonResult<T> error(ServiceException serviceException) {
-        return error(serviceException.getCode(), serviceException.getMessage());
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/PageParam.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/PageParam.java
deleted file mode 100644
index 6d7df45..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/PageParam.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.framework.common.pojo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.Min;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.NotNull;
-import java.io.Serializable;
-
-@Schema(description="分页参数")
-@Data
-public class PageParam implements Serializable {
-
-    private static final Integer PAGE_NO = 1;
-    private static final Integer PAGE_SIZE = 10;
-
-    /**
-     * 每页条数 - 不分页
-     *
-     * 例如说,导出接口,可以设置 {@link #pageSize} 为 -1 不分页,查询所有数据。
-     */
-    public static final Integer PAGE_SIZE_NONE = -1;
-
-    @Schema(description = "页码,从 1 开始", requiredMode = Schema.RequiredMode.REQUIRED,example = "1")
-    @NotNull(message = "页码不能为空")
-    @Min(value = 1, message = "页码最小值为 1")
-    private Integer pageNo = PAGE_NO;
-
-    @Schema(description = "每页条数,最大值为 100", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @NotNull(message = "每页条数不能为空")
-    @Min(value = 1, message = "每页条数最小值为 1")
-    @Max(value = 100, message = "每页条数最大值为 100")
-    private Integer pageSize = PAGE_SIZE;
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/PageResult.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/PageResult.java
deleted file mode 100644
index bee40ce..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/PageResult.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.iailab.framework.common.pojo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-@Schema(description = "分页结果")
-@Data
-public final class PageResult<T> implements Serializable {
-
-    @Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED)
-    private List<T> list;
-
-    @Schema(description = "总量", requiredMode = Schema.RequiredMode.REQUIRED)
-    private Long total;
-
-    public PageResult() {
-    }
-
-    public PageResult(List<T> list, Long total) {
-        this.list = list;
-        this.total = total;
-    }
-
-    public PageResult(Long total) {
-        this.list = new ArrayList<>();
-        this.total = total;
-    }
-
-    public static <T> PageResult<T> empty() {
-        return new PageResult<>(0L);
-    }
-
-    public static <T> PageResult<T> empty(Long total) {
-        return new PageResult<>(total);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/SortablePageParam.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/SortablePageParam.java
deleted file mode 100644
index 668725f..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/SortablePageParam.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.framework.common.pojo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import java.util.List;
-
-@Schema(description = "可排序的分页参数")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SortablePageParam extends PageParam {
-
-    @Schema(description = "排序字段")
-    private List<SortingField> sortingFields;
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/SortingField.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/SortingField.java
deleted file mode 100644
index 3063446..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/pojo/SortingField.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.common.pojo;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serializable;
-
-/**
- * 排序字段 DTO
- *
- * 类名加了 ing 的原因是,避免和 ES SortField 重名。
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class SortingField implements Serializable {
-
-    /**
-     * 顺序 - 升序
-     */
-    public static final String ORDER_ASC = "asc";
-    /**
-     * 顺序 - 降序
-     */
-    public static final String ORDER_DESC = "desc";
-
-    /**
-     * 字段
-     */
-    private String field;
-    /**
-     * 顺序
-     */
-    private String order;
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/cache/CacheUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/cache/CacheUtils.java
deleted file mode 100644
index 528af27..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/cache/CacheUtils.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.iailab.framework.common.util.cache;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-import java.time.Duration;
-import java.util.concurrent.Executors;
-
-/**
- * Cache 工具类
- *
- * @author iailab
- */
-public class CacheUtils {
-
-    /**
-     * 构建异步刷新的 LoadingCache 对象
-     *
-     * 注意:如果你的缓存和 ThreadLocal 有关系,要么自己处理 ThreadLocal 的传递,要么使用 {@link #buildCache(Duration, CacheLoader)} 方法
-     *
-     * 或者简单理解:
-     * 1、和“人”相关的,使用 {@link #buildCache(Duration, CacheLoader)} 方法
-     * 2、和“全局”、“系统”相关的,使用当前缓存方法
-     *
-     * @param duration 过期时间
-     * @param loader  CacheLoader 对象
-     * @return LoadingCache 对象
-     */
-    public static <K, V> LoadingCache<K, V> buildAsyncReloadingCache(Duration duration, CacheLoader<K, V> loader) {
-        return CacheBuilder.newBuilder()
-                // 只阻塞当前数据加载线程,其他线程返回旧值
-                .refreshAfterWrite(duration)
-                // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
-                .build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO iailab:可能要思考下,未来要不要做成可配置
-    }
-
-    /**
-     * 构建同步刷新的 LoadingCache 对象
-     *
-     * @param duration 过期时间
-     * @param loader  CacheLoader 对象
-     * @return LoadingCache 对象
-     */
-    public static <K, V> LoadingCache<K, V> buildCache(Duration duration, CacheLoader<K, V> loader) {
-        return CacheBuilder.newBuilder().refreshAfterWrite(duration).build(loader);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/ArrayUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/ArrayUtils.java
deleted file mode 100644
index 4fba745..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/ArrayUtils.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.iailab.framework.common.util.collection;
-
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.collection.IterUtil;
-import cn.hutool.core.util.ArrayUtil;
-
-import java.util.Collection;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
-
-/**
- * Array 工具类
- *
- * @author iailab
- */
-public class ArrayUtils {
-
-    /**
-     * 将 object 和 newElements 合并成一个数组
-     *
-     * @param object 对象
-     * @param newElements 数组
-     * @param <T> 泛型
-     * @return 结果数组
-     */
-    @SafeVarargs
-    public static <T> Consumer<T>[] append(Consumer<T> object, Consumer<T>... newElements) {
-        if (object == null) {
-            return newElements;
-        }
-        Consumer<T>[] result = ArrayUtil.newArray(Consumer.class, 1 + newElements.length);
-        result[0] = object;
-        System.arraycopy(newElements, 0, result, 1, newElements.length);
-        return result;
-    }
-
-    public static <T, V> V[] toArray(Collection<T> from, Function<T, V> mapper) {
-        return toArray(convertList(from, mapper));
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> T[] toArray(Collection<T> from) {
-        if (CollectionUtil.isEmpty(from)) {
-            return (T[]) (new Object[0]);
-        }
-        return ArrayUtil.toArray(from, (Class<T>) IterUtil.getElementType(from.iterator()));
-    }
-
-    public static <T> T get(T[] array, int index) {
-        if (null == array || index >= array.length) {
-            return null;
-        }
-        return array[index];
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/CollectionUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/CollectionUtils.java
deleted file mode 100644
index 9b972c9..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/CollectionUtils.java
+++ /dev/null
@@ -1,338 +0,0 @@
-package com.iailab.framework.common.util.collection;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.ArrayUtil;
-import com.google.common.collect.ImmutableMap;
-import com.iailab.framework.common.pojo.PageResult;
-
-import java.util.*;
-import java.util.function.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.util.Arrays.asList;
-
-/**
- * Collection 工具类
- *
- * @author iailab
- */
-public class CollectionUtils {
-
-    public static boolean containsAny(Object source, Object... targets) {
-        return asList(targets).contains(source);
-    }
-
-    public static boolean isAnyEmpty(Collection<?>... collections) {
-        return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty);
-    }
-
-    public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) {
-        return from.stream().anyMatch(predicate);
-    }
-
-    public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().filter(predicate).collect(Collectors.toList());
-    }
-
-    public static <T, R> List<T> distinct(Collection<T> from, Function<T, R> keyMapper) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return distinct(from, keyMapper, (t1, t2) -> t1);
-    }
-
-    public static <T, R> List<T> distinct(Collection<T> from, Function<T, R> keyMapper, BinaryOperator<T> cover) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return new ArrayList<>(convertMap(from, keyMapper, Function.identity(), cover).values());
-    }
-
-    public static <T, U> List<U> convertList(T[] from, Function<T, U> func) {
-        if (ArrayUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return convertList(Arrays.asList(from), func);
-    }
-
-    public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func, Predicate<T> filter) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U> PageResult<U> convertPage(PageResult<T> from, Function<T, U> func) {
-        if (ArrayUtil.isEmpty(from)) {
-            return new PageResult<>(from.getTotal());
-        }
-        return new PageResult<>(convertList(from.getList(), func), from.getTotal());
-    }
-
-    public static <T, U> List<U> convertListByFlatMap(Collection<T> from,
-                                                      Function<T, ? extends Stream<? extends U>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().filter(Objects::nonNull).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <T, U, R> List<R> convertListByFlatMap(Collection<T> from,
-                                                         Function<? super T, ? extends U> mapper,
-                                                         Function<U, ? extends Stream<? extends R>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new ArrayList<>();
-        }
-        return from.stream().map(mapper).filter(Objects::nonNull).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList());
-    }
-
-    public static <K, V> List<V> mergeValuesFromMap(Map<K, List<V>> map) {
-        return map.values()
-                .stream()
-                .flatMap(List::stream)
-                .collect(Collectors.toList());
-    }
-
-    public static <T> Set<T> convertSet(Collection<T> from) {
-        return convertSet(from, v -> v);
-    }
-
-    public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
-    public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func, Predicate<T> filter) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
-    public static <T, K> Map<K, T> convertMapByFilter(Collection<T> from, Predicate<T> filter, Function<T, K> keyFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return from.stream().filter(filter).collect(Collectors.toMap(keyFunc, v -> v));
-    }
-
-    public static <T, U> Set<U> convertSetByFlatMap(Collection<T> from,
-                                                    Function<T, ? extends Stream<? extends U>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().filter(Objects::nonNull).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
-    public static <T, U, R> Set<R> convertSetByFlatMap(Collection<T> from,
-                                                       Function<? super T, ? extends U> mapper,
-                                                       Function<U, ? extends Stream<? extends R>> func) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashSet<>();
-        }
-        return from.stream().map(mapper).filter(Objects::nonNull).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
-
-    public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return convertMap(from, keyFunc, Function.identity());
-    }
-
-    public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc, Supplier<? extends Map<K, T>> supplier) {
-        if (CollUtil.isEmpty(from)) {
-            return supplier.get();
-        }
-        return convertMap(from, keyFunc, Function.identity(), supplier);
-    }
-
-    public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1);
-    }
-
-    public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc, BinaryOperator<V> mergeFunction) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return convertMap(from, keyFunc, valueFunc, mergeFunction, HashMap::new);
-    }
-
-    public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc, Supplier<? extends Map<K, V>> supplier) {
-        if (CollUtil.isEmpty(from)) {
-            return supplier.get();
-        }
-        return convertMap(from, keyFunc, valueFunc, (v1, v2) -> v1, supplier);
-    }
-
-    public static <T, K, V> Map<K, V> convertMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc, BinaryOperator<V> mergeFunction, Supplier<? extends Map<K, V>> supplier) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return from.stream().collect(Collectors.toMap(keyFunc, valueFunc, mergeFunction, supplier));
-    }
-
-    public static <T, K> Map<K, List<T>> convertMultiMap(Collection<T> from, Function<T, K> keyFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(t -> t, Collectors.toList())));
-    }
-
-    public static <T, K, V> Map<K, List<V>> convertMultiMap(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return from.stream()
-                .collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toList())));
-    }
-
-    // 暂时没想好名字,先以 2 结尾噶
-    public static <T, K, V> Map<K, Set<V>> convertMultiMap2(Collection<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return new HashMap<>();
-        }
-        return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toSet())));
-    }
-
-    public static <T, K> Map<K, T> convertImmutableMap(Collection<T> from, Function<T, K> keyFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return Collections.emptyMap();
-        }
-        ImmutableMap.Builder<K, T> builder = ImmutableMap.builder();
-        from.forEach(item -> builder.put(keyFunc.apply(item), item));
-        return builder.build();
-    }
-
-    /**
-     * 对比老、新两个列表,找出新增、修改、删除的数据
-     *
-     * @param oldList  老列表
-     * @param newList  新列表
-     * @param sameFunc 对比函数,返回 true 表示相同,返回 false 表示不同
-     *                 注意,same 是通过每个元素的“标识”,判断它们是不是同一个数据
-     * @return [新增列表、修改列表、删除列表]
-     */
-    public static <T> List<List<T>> diffList(Collection<T> oldList, Collection<T> newList,
-                                             BiFunction<T, T, Boolean> sameFunc) {
-        List<T> createList = new LinkedList<>(newList); // 默认都认为是新增的,后续会进行移除
-        List<T> updateList = new ArrayList<>();
-        List<T> deleteList = new ArrayList<>();
-
-        // 通过以 oldList 为主遍历,找出 updateList 和 deleteList
-        for (T oldObj : oldList) {
-            // 1. 寻找是否有匹配的
-            T foundObj = null;
-            for (Iterator<T> iterator = createList.iterator(); iterator.hasNext(); ) {
-                T newObj = iterator.next();
-                // 1.1 不匹配,则直接跳过
-                if (!sameFunc.apply(oldObj, newObj)) {
-                    continue;
-                }
-                // 1.2 匹配,则移除,并结束寻找
-                iterator.remove();
-                foundObj = newObj;
-                break;
-            }
-            // 2. 匹配添加到 updateList;不匹配则添加到 deleteList 中
-            if (foundObj != null) {
-                updateList.add(foundObj);
-            } else {
-                deleteList.add(oldObj);
-            }
-        }
-        return asList(createList, updateList, deleteList);
-    }
-
-    public static boolean containsAny(Collection<?> source, Collection<?> candidates) {
-        return org.springframework.util.CollectionUtils.containsAny(source, candidates);
-    }
-
-    public static <T> T getFirst(List<T> from) {
-        return !CollectionUtil.isEmpty(from) ? from.get(0) : null;
-    }
-
-    public static <T> T findFirst(Collection<T> from, Predicate<T> predicate) {
-        return findFirst(from, predicate, Function.identity());
-    }
-
-    public static <T, U> U findFirst(Collection<T> from, Predicate<T> predicate, Function<T, U> func) {
-        if (CollUtil.isEmpty(from)) {
-            return null;
-        }
-        return from.stream().filter(predicate).findFirst().map(func).orElse(null);
-    }
-
-    public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> from, Function<T, V> valueFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return null;
-        }
-        assert !from.isEmpty(); // 断言,避免告警
-        T t = from.stream().max(Comparator.comparing(valueFunc)).get();
-        return valueFunc.apply(t);
-    }
-
-    public static <T, V extends Comparable<? super V>> V getMinValue(List<T> from, Function<T, V> valueFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return null;
-        }
-        assert from.size() > 0; // 断言,避免告警
-        T t = from.stream().min(Comparator.comparing(valueFunc)).get();
-        return valueFunc.apply(t);
-    }
-
-    public static <T, V extends Comparable<? super V>> T getMinObject(List<T> from, Function<T, V> valueFunc) {
-        if (CollUtil.isEmpty(from)) {
-            return null;
-        }
-        assert from.size() > 0; // 断言,避免告警
-        return from.stream().min(Comparator.comparing(valueFunc)).get();
-    }
-
-    public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc,
-                                                                     BinaryOperator<V> accumulator) {
-        return getSumValue(from, valueFunc, accumulator, null);
-    }
-
-    public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc,
-                                                                     BinaryOperator<V> accumulator, V defaultValue) {
-        if (CollUtil.isEmpty(from)) {
-            return defaultValue;
-        }
-        assert !from.isEmpty(); // 断言,避免告警
-        return from.stream().map(valueFunc).filter(Objects::nonNull).reduce(accumulator).orElse(defaultValue);
-    }
-
-    public static <T> void addIfNotNull(Collection<T> coll, T item) {
-        if (item == null) {
-            return;
-        }
-        coll.add(item);
-    }
-
-    public static <T> Collection<T> singleton(T obj) {
-        return obj == null ? Collections.emptyList() : Collections.singleton(obj);
-    }
-
-    public static <T> List<T> newArrayList(List<List<T>> list) {
-        return list.stream().filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList());
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/MapUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/MapUtils.java
deleted file mode 100644
index 921dcbe..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/MapUtils.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.iailab.framework.common.util.collection;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.ObjUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-
-/**
- * Map 工具类
- *
- * @author iailab
- */
-public class MapUtils {
-
-    /**
-     * 从哈希表表中,获得 keys 对应的所有 value 数组
-     *
-     * @param multimap 哈希表
-     * @param keys keys
-     * @return value 数组
-     */
-    public static <K, V> List<V> getList(Multimap<K, V> multimap, Collection<K> keys) {
-        List<V> result = new ArrayList<>();
-        keys.forEach(k -> {
-            Collection<V> values = multimap.get(k);
-            if (CollectionUtil.isEmpty(values)) {
-                return;
-            }
-            result.addAll(values);
-        });
-        return result;
-    }
-
-    /**
-     * 从哈希表查找到 key 对应的 value,然后进一步处理
-     * key 为 null 时, 不处理
-     * 注意,如果查找到的 value 为 null 时,不进行处理
-     *
-     * @param map 哈希表
-     * @param key key
-     * @param consumer 进一步处理的逻辑
-     */
-    public static <K, V> void findAndThen(Map<K, V> map, K key, Consumer<V> consumer) {
-        if (ObjUtil.isNull(key) || CollUtil.isEmpty(map)) {
-            return;
-        }
-        V value = map.get(key);
-        if (value == null) {
-            return;
-        }
-        consumer.accept(value);
-    }
-
-    public static <K, V> Map<K, V> convertMap(List<KeyValue<K, V>> keyValues) {
-        Map<K, V> map = Maps.newLinkedHashMapWithExpectedSize(keyValues.size());
-        keyValues.forEach(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
-        return map;
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/SetUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/SetUtils.java
deleted file mode 100644
index 8777ee6..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/collection/SetUtils.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.framework.common.util.collection;
-
-import cn.hutool.core.collection.CollUtil;
-
-import java.util.Set;
-
-/**
- * Set 工具类
- *
- * @author iailab
- */
-public class SetUtils {
-
-    @SafeVarargs
-    public static <T> Set<T> asSet(T... objs) {
-        return CollUtil.newHashSet(objs);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/DateUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/DateUtils.java
deleted file mode 100644
index 39f8a7e..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/DateUtils.java
+++ /dev/null
@@ -1,304 +0,0 @@
-package com.iailab.framework.common.util.date;
-
-import cn.hutool.core.date.LocalDateTimeUtil;
-import org.joda.time.DateTime;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.time.*;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 时间工具类
- *
- * @author iailab
- */
-public class DateUtils {
-
-    /**
-     * 时区 - 默认
-     */
-    public static final String TIME_ZONE_DEFAULT = "GMT+8";
-
-    /**
-     * 秒转换成毫秒
-     */
-    public static final long SECOND_MILLIS = 1000;
-
-    public static final String FORMAT_YEAR_MONTH_DAY = "yyyy-MM-dd";
-    /** 时间格式(yyyy.MM.dd) */
-    public final static String DATE_PATTERN_POINT = "yyyy.MM.dd";
-
-    public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";
-
-    public final static String DATE_TIME_PATTERN_STRING = "yyyyMMddHHmmss";
-
-    public static final String FORMAT_SIMPLE_TIME = "HH:mm";
-
-    /**
-     * 日期格式化 日期格式为:yyyy-MM-dd
-     * @param date  日期
-     * @return  返回yyyy-MM-dd格式日期
-     */
-    public static String format(Date date) {
-        return format(date, FORMAT_YEAR_MONTH_DAY);
-    }
-
-    /**
-     * 日期格式化 日期格式为:yyyy-MM-dd
-     * @param date  日期
-     * @param pattern  格式,如:DateUtils.DATE_TIME_PATTERN
-     * @return  返回yyyy-MM-dd格式日期
-     */
-    public static String format(Date date, String pattern) {
-        if(date != null){
-            SimpleDateFormat df = new SimpleDateFormat(pattern);
-            return df.format(date);
-        }
-        return null;
-    }
-
-    /**
-     * 日期解析
-     * @param date  日期
-     * @param pattern  格式,如:DateUtils.DATE_TIME_PATTERN
-     * @return  返回Date
-     */
-    public static Date parse(String date, String pattern) {
-        try {
-            return new SimpleDateFormat(pattern).parse(date);
-        } catch (ParseException e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-    /**
-     * 将 LocalDateTime 转换成 Date
-     *
-     * @param date LocalDateTime
-     * @return LocalDateTime
-     */
-    public static Date of(LocalDateTime date) {
-        if (date == null) {
-            return null;
-        }
-        // 将此日期时间与时区相结合以创建 ZonedDateTime
-        ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault());
-        // 本地时间线 LocalDateTime 到即时时间线 Instant 时间戳
-        Instant instant = zonedDateTime.toInstant();
-        // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间
-        return Date.from(instant);
-    }
-
-    /**
-     * 将 Date 转换成 LocalDateTime
-     *
-     * @param date Date
-     * @return LocalDateTime
-     */
-    public static LocalDateTime of(Date date) {
-        if (date == null) {
-            return null;
-        }
-        // 转为时间戳
-        Instant instant = date.toInstant();
-        // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间
-        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
-    }
-
-    public static Date addTime(Duration duration) {
-        return new Date(System.currentTimeMillis() + duration.toMillis());
-    }
-
-    public static boolean isExpired(LocalDateTime time) {
-        LocalDateTime now = LocalDateTime.now();
-        return now.isAfter(time);
-    }
-
-    /**
-     * 创建指定时间
-     *
-     * @param year  年
-     * @param mouth 月
-     * @param day   日
-     * @return 指定时间
-     */
-    public static Date buildTime(int year, int mouth, int day) {
-        return buildTime(year, mouth, day, 0, 0, 0);
-    }
-
-    /**
-     * 创建指定时间
-     *
-     * @param year   年
-     * @param mouth  月
-     * @param day    日
-     * @param hour   小时
-     * @param minute 分钟
-     * @param second 秒
-     * @return 指定时间
-     */
-    public static Date buildTime(int year, int mouth, int day,
-                                 int hour, int minute, int second) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.set(Calendar.YEAR, year);
-        calendar.set(Calendar.MONTH, mouth - 1);
-        calendar.set(Calendar.DAY_OF_MONTH, day);
-        calendar.set(Calendar.HOUR_OF_DAY, hour);
-        calendar.set(Calendar.MINUTE, minute);
-        calendar.set(Calendar.SECOND, second);
-        calendar.set(Calendar.MILLISECOND, 0); // 一般情况下,都是 0 毫秒
-        return calendar.getTime();
-    }
-
-    public static Date max(Date a, Date b) {
-        if (a == null) {
-            return b;
-        }
-        if (b == null) {
-            return a;
-        }
-        return a.compareTo(b) > 0 ? a : b;
-    }
-
-    public static LocalDateTime max(LocalDateTime a, LocalDateTime b) {
-        if (a == null) {
-            return b;
-        }
-        if (b == null) {
-            return a;
-        }
-        return a.isAfter(b) ? a : b;
-    }
-
-    /**
-     * 是否今天
-     *
-     * @param date 日期
-     * @return 是否
-     */
-    public static boolean isToday(LocalDateTime date) {
-        return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now());
-    }
-
-    /**
-     * 是否昨天
-     *
-     * @param date 日期
-     * @return 是否
-     */
-    public static boolean isYesterday(LocalDateTime date) {
-        return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now().minusDays(1));
-    }
-
-    public static List<String> getTimeScale(Date startDate, Date endDate, int seconds) {
-        List<String> days = new ArrayList<String>();
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(startDate);
-        while (calendar.getTime().compareTo(endDate) <= 0) {
-            days.add(DateUtils.format(calendar.getTime(), FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND));
-            calendar.add(Calendar.SECOND, seconds);
-        }
-        return days;
-    }
-
-    public static List<String> getTimeScale(Date startDate, Date endDate, int seconds, String timeFormat) {
-        List<String> days = new ArrayList<String>();
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(startDate);
-        while (calendar.getTime().compareTo(endDate) <= 0) {
-            days.add(DateUtils.format(calendar.getTime(), timeFormat));
-            calendar.add(Calendar.SECOND, seconds);
-        }
-        return days;
-    }
-
-    /**
-     * 对日期的【秒】进行加/减
-     *
-     * @param date 日期
-     * @param seconds 秒数,负数为减
-     * @return 加/减几秒后的日期
-     */
-    public static Date addDateSeconds(Date date, int seconds) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusSeconds(seconds).toDate();
-    }
-
-    /**
-     * 对日期的【分钟】进行加/减
-     *
-     * @param date 日期
-     * @param minutes 分钟数,负数为减
-     * @return 加/减几分钟后的日期
-     */
-    public static Date addDateMinutes(Date date, int minutes) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusMinutes(minutes).toDate();
-    }
-
-    /**
-     * 对日期的【小时】进行加/减
-     *
-     * @param date 日期
-     * @param hours 小时数,负数为减
-     * @return 加/减几小时后的日期
-     */
-    public static Date addDateHours(Date date, int hours) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusHours(hours).toDate();
-    }
-
-    /**
-     * 对日期的【天】进行加/减
-     *
-     * @param date 日期
-     * @param days 天数,负数为减
-     * @return 加/减几天后的日期
-     */
-    public static Date addDateDays(Date date, int days) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusDays(days).toDate();
-    }
-
-    /**
-     * 对日期的【周】进行加/减
-     *
-     * @param date 日期
-     * @param weeks 周数,负数为减
-     * @return 加/减几周后的日期
-     */
-    public static Date addDateWeeks(Date date, int weeks) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusWeeks(weeks).toDate();
-    }
-
-    /**
-     * 对日期的【月】进行加/减
-     *
-     * @param date 日期
-     * @param months 月数,负数为减
-     * @return 加/减几月后的日期
-     */
-    public static Date addDateMonths(Date date, int months) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusMonths(months).toDate();
-    }
-
-    /**
-     * 对日期的【年】进行加/减
-     *
-     * @param date 日期
-     * @param years 年数,负数为减
-     * @return 加/减几年后的日期
-     */
-    public static Date addDateYears(Date date, int years) {
-        DateTime dateTime = new DateTime(date);
-        return dateTime.plusYears(years).toDate();
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/LocalDateTimeUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/LocalDateTimeUtils.java
deleted file mode 100644
index a54b17c..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/date/LocalDateTimeUtils.java
+++ /dev/null
@@ -1,309 +0,0 @@
-package com.iailab.framework.common.util.date;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.enums.DateIntervalEnum;
-
-import java.time.*;
-import java.time.format.DateTimeParseException;
-import java.time.temporal.ChronoUnit;
-import java.time.temporal.TemporalAdjusters;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 时间工具类,用于 {@link java.time.LocalDateTime}
- *
- * @author iailab
- */
-public class LocalDateTimeUtils {
-
-    /**
-     * 空的 LocalDateTime 对象,主要用于 DB 唯一索引的默认值
-     */
-    public static LocalDateTime EMPTY = buildTime(1970, 1, 1);
-
-    /**
-     * 解析时间
-     *
-     * 相比 {@link LocalDateTimeUtil#parse(CharSequence)} 方法来说,会尽量去解析,直到成功
-     *
-     * @param time 时间
-     * @return 时间字符串
-     */
-    public static LocalDateTime parse(String time) {
-        try {
-            return LocalDateTimeUtil.parse(time, DatePattern.NORM_DATE_PATTERN);
-        } catch (DateTimeParseException e) {
-            return LocalDateTimeUtil.parse(time);
-        }
-    }
-
-    public static LocalDateTime addTime(Duration duration) {
-        return LocalDateTime.now().plus(duration);
-    }
-
-    public static LocalDateTime minusTime(Duration duration) {
-        return LocalDateTime.now().minus(duration);
-    }
-
-    public static boolean beforeNow(LocalDateTime date) {
-        return date.isBefore(LocalDateTime.now());
-    }
-
-    public static boolean afterNow(LocalDateTime date) {
-        return date.isAfter(LocalDateTime.now());
-    }
-
-    /**
-     * 创建指定时间
-     *
-     * @param year  年
-     * @param mouth 月
-     * @param day   日
-     * @return 指定时间
-     */
-    public static LocalDateTime buildTime(int year, int mouth, int day) {
-        return LocalDateTime.of(year, mouth, day, 0, 0, 0);
-    }
-
-    public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1,
-                                                   int year2, int mouth2, int day2) {
-        return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)};
-    }
-
-    /**
-     * 判指定断时间,是否在该时间范围内
-     *
-     * @param startTime 开始时间
-     * @param endTime 结束时间
-     * @param time 指定时间
-     * @return 是否
-     */
-    public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, String time) {
-        if (startTime == null || endTime == null || time == null) {
-            return false;
-        }
-        return LocalDateTimeUtil.isIn(parse(time), startTime, endTime);
-    }
-
-    /**
-     * 判断当前时间是否在该时间范围内
-     *
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     * @return 是否
-     */
-    public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime) {
-        if (startTime == null || endTime == null) {
-            return false;
-        }
-        return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
-    }
-
-    /**
-     * 判断当前时间是否在该时间范围内
-     *
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     * @return 是否
-     */
-    public static boolean isBetween(String startTime, String endTime) {
-        if (startTime == null || endTime == null) {
-            return false;
-        }
-        LocalDate nowDate = LocalDate.now();
-        return LocalDateTimeUtil.isIn(LocalDateTime.now(),
-                LocalDateTime.of(nowDate, LocalTime.parse(startTime)),
-                LocalDateTime.of(nowDate, LocalTime.parse(endTime)));
-    }
-
-    /**
-     * 判断时间段是否重叠
-     *
-     * @param startTime1 开始 time1
-     * @param endTime1   结束 time1
-     * @param startTime2 开始 time2
-     * @param endTime2   结束 time2
-     * @return 重叠:true 不重叠:false
-     */
-    public static boolean isOverlap(LocalTime startTime1, LocalTime endTime1, LocalTime startTime2, LocalTime endTime2) {
-        LocalDate nowDate = LocalDate.now();
-        return LocalDateTimeUtil.isOverlap(LocalDateTime.of(nowDate, startTime1), LocalDateTime.of(nowDate, endTime1),
-                LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2));
-    }
-
-    /**
-     * 获取指定日期所在的月份的开始时间
-     * 例如:2023-09-30 00:00:00,000
-     *
-     * @param date 日期
-     * @return 月份的开始时间
-     */
-    public static LocalDateTime beginOfMonth(LocalDateTime date) {
-        return date.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
-    }
-
-    /**
-     * 获取指定日期所在的月份的最后时间
-     * 例如:2023-09-30 23:59:59,999
-     *
-     * @param date 日期
-     * @return 月份的结束时间
-     */
-    public static LocalDateTime endOfMonth(LocalDateTime date) {
-        return date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
-    }
-
-    /**
-     * 获得指定日期所在季度
-     *
-     * @param date 日期
-     * @return 所在季度
-     */
-    public static int getQuarterOfYear(LocalDateTime date) {
-        return (date.getMonthValue() - 1) / 3 + 1;
-    }
-
-    /**
-     * 获取指定日期到现在过了几天,如果指定日期在当前日期之后,获取结果为负
-     *
-     * @param dateTime 日期
-     * @return 相差天数
-     */
-    public static Long between(LocalDateTime dateTime) {
-        return LocalDateTimeUtil.between(dateTime, LocalDateTime.now(), ChronoUnit.DAYS);
-    }
-
-    /**
-     * 获取今天的开始时间
-     *
-     * @return 今天
-     */
-    public static LocalDateTime getToday() {
-        return LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
-    }
-
-    /**
-     * 获取昨天的开始时间
-     *
-     * @return 昨天
-     */
-    public static LocalDateTime getYesterday() {
-        return LocalDateTimeUtil.beginOfDay(LocalDateTime.now().minusDays(1));
-    }
-
-    /**
-     * 获取本月的开始时间
-     *
-     * @return 本月
-     */
-    public static LocalDateTime getMonth() {
-        return beginOfMonth(LocalDateTime.now());
-    }
-
-    /**
-     * 获取本年的开始时间
-     *
-     * @return 本年
-     */
-    public static LocalDateTime getYear() {
-        return LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
-    }
-
-    public static List<LocalDateTime[]> getDateRangeList(LocalDateTime startTime,
-                                                         LocalDateTime endTime,
-                                                         Integer interval) {
-        // 1.1 找到枚举
-        DateIntervalEnum intervalEnum = DateIntervalEnum.valueOf(interval);
-        Assert.notNull(intervalEnum, "interval({}} 找不到对应的枚举", interval);
-        // 1.2 将时间对齐
-        startTime = LocalDateTimeUtil.beginOfDay(startTime);
-        endTime = LocalDateTimeUtil.endOfDay(endTime);
-
-        // 2. 循环,生成时间范围
-        List<LocalDateTime[]> timeRanges = new ArrayList<>();
-        switch (intervalEnum) {
-            case DAY:
-                while (startTime.isBefore(endTime)) {
-                    timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)});
-                    startTime = startTime.plusDays(1);
-                }
-                break;
-            case WEEK:
-                while (startTime.isBefore(endTime)) {
-                    LocalDateTime endOfWeek = startTime.with(DayOfWeek.SUNDAY).plusDays(1).minusNanos(1);
-                    timeRanges.add(new LocalDateTime[]{startTime, endOfWeek});
-                    startTime = endOfWeek.plusNanos(1);
-                }
-                break;
-            case MONTH:
-                while (startTime.isBefore(endTime)) {
-                    LocalDateTime endOfMonth = startTime.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1).minusNanos(1);
-                    timeRanges.add(new LocalDateTime[]{startTime, endOfMonth});
-                    startTime = endOfMonth.plusNanos(1);
-                }
-                break;
-            case QUARTER:
-                while (startTime.isBefore(endTime)) {
-                    int quarterOfYear = getQuarterOfYear(startTime);
-                    LocalDateTime quarterEnd = quarterOfYear == 4
-                            ? startTime.with(TemporalAdjusters.lastDayOfYear()).plusDays(1).minusNanos(1)
-                            : startTime.withMonth(quarterOfYear * 3 + 1).withDayOfMonth(1).minusNanos(1);
-                    timeRanges.add(new LocalDateTime[]{startTime, quarterEnd});
-                    startTime = quarterEnd.plusNanos(1);
-                }
-                break;
-            case YEAR:
-                while (startTime.isBefore(endTime)) {
-                    LocalDateTime endOfYear = startTime.with(TemporalAdjusters.lastDayOfYear()).plusDays(1).minusNanos(1);
-                    timeRanges.add(new LocalDateTime[]{startTime, endOfYear});
-                    startTime = endOfYear.plusNanos(1);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Invalid interval: " + interval);
-        }
-        // 3. 兜底,最后一个时间,需要保持在 endTime 之前
-        LocalDateTime[] lastTimeRange = CollUtil.getLast(timeRanges);
-        if (lastTimeRange != null) {
-            lastTimeRange[1] = endTime;
-        }
-        return timeRanges;
-    }
-
-    /**
-     * 格式化时间范围
-     *
-     * @param startTime 开始时间
-     * @param endTime   结束时间
-     * @param interval  时间间隔
-     * @return 时间范围
-     */
-    public static String formatDateRange(LocalDateTime startTime, LocalDateTime endTime, Integer interval) {
-        // 1. 找到枚举
-        DateIntervalEnum intervalEnum = DateIntervalEnum.valueOf(interval);
-        Assert.notNull(intervalEnum, "interval({}} 找不到对应的枚举", interval);
-
-        // 2. 循环,生成时间范围
-        switch (intervalEnum) {
-            case DAY:
-                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN);
-            case WEEK:
-                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN)
-                        + StrUtil.format("(第 {} 周)", LocalDateTimeUtil.weekOfYear(startTime));
-            case MONTH:
-                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_MONTH_PATTERN);
-            case QUARTER:
-                return StrUtil.format("{}-Q{}", startTime.getYear(), getQuarterOfYear(startTime));
-            case YEAR:
-                return LocalDateTimeUtil.format(startTime, DatePattern.NORM_YEAR_PATTERN);
-            default:
-                throw new IllegalArgumentException("Invalid interval: " + interval);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/http/HttpUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/http/HttpUtils.java
deleted file mode 100644
index 1728905..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/http/HttpUtils.java
+++ /dev/null
@@ -1,385 +0,0 @@
-package com.iailab.framework.common.util.http;
-
-import cn.hutool.core.codec.Base64;
-import cn.hutool.core.map.TableMap;
-import cn.hutool.core.net.url.UrlBuilder;
-import cn.hutool.core.util.ReflectUtil;
-import cn.hutool.core.util.StrUtil;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-import org.springframework.web.util.UriComponents;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Map;
-
-/**
- * HTTP 工具类
- *
- * @author iailab
- */
-public class HttpUtils {
-
-    @SuppressWarnings("unchecked")
-    public static String replaceUrlQuery(String url, String key, String value) {
-        UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());
-        // 先移除
-        TableMap<CharSequence, CharSequence> query = (TableMap<CharSequence, CharSequence>)
-                ReflectUtil.getFieldValue(builder.getQuery(), "query");
-        query.remove(key);
-        // 后添加
-        builder.addQuery(key, value);
-        return builder.build();
-    }
-
-    private String append(String base, Map<String, ?> query, boolean fragment) {
-        return append(base, query, null, fragment);
-    }
-
-    /**
-     * 拼接 URL
-     *
-     * copy from Spring Security OAuth2 的 AuthorizationEndpoint 类的 append 方法
-     *
-     * @param base 基础 URL
-     * @param query 查询参数
-     * @param keys query 的 key,对应的原本的 key 的映射。例如说 query 里有个 key 是 xx,实际它的 key 是 extra_xx,则通过 keys 里添加这个映射
-     * @param fragment URL 的 fragment,即拼接到 # 中
-     * @return 拼接后的 URL
-     */
-    public static String append(String base, Map<String, ?> query, Map<String, String> keys, boolean fragment) {
-        UriComponentsBuilder template = UriComponentsBuilder.newInstance();
-        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(base);
-        URI redirectUri;
-        try {
-            // assume it's encoded to start with (if it came in over the wire)
-            redirectUri = builder.build(true).toUri();
-        } catch (Exception e) {
-            // ... but allow client registrations to contain hard-coded non-encoded values
-            redirectUri = builder.build().toUri();
-            builder = UriComponentsBuilder.fromUri(redirectUri);
-        }
-        template.scheme(redirectUri.getScheme()).port(redirectUri.getPort()).host(redirectUri.getHost())
-                .userInfo(redirectUri.getUserInfo()).path(redirectUri.getPath());
-
-        if (fragment) {
-            StringBuilder values = new StringBuilder();
-            if (redirectUri.getFragment() != null) {
-                String append = redirectUri.getFragment();
-                values.append(append);
-            }
-            for (String key : query.keySet()) {
-                if (values.length() > 0) {
-                    values.append("&");
-                }
-                String name = key;
-                if (keys != null && keys.containsKey(key)) {
-                    name = keys.get(key);
-                }
-                values.append(name).append("={").append(key).append("}");
-            }
-            if (values.length() > 0) {
-                template.fragment(values.toString());
-            }
-            UriComponents encoded = template.build().expand(query).encode();
-            builder.fragment(encoded.getFragment());
-        } else {
-            for (String key : query.keySet()) {
-                String name = key;
-                if (keys != null && keys.containsKey(key)) {
-                    name = keys.get(key);
-                }
-                template.queryParam(name, "{" + key + "}");
-            }
-            template.fragment(redirectUri.getFragment());
-            UriComponents encoded = template.build().expand(query).encode();
-            builder.query(encoded.getQuery());
-        }
-        return builder.build().toUriString();
-    }
-
-    public static String[] obtainBasicAuthorization(HttpServletRequest request) {
-        String clientId;
-        String clientSecret;
-        // 先从 Header 中获取
-        String authorization = request.getHeader("Authorization");
-        authorization = StrUtil.subAfter(authorization, "Basic ", true);
-        if (StringUtils.hasText(authorization)) {
-            authorization = Base64.decodeStr(authorization);
-            clientId = StrUtil.subBefore(authorization, ":", false);
-            clientSecret = StrUtil.subAfter(authorization, ":", false);
-        // 再从 Param 中获取
-        } else {
-            clientId = request.getParameter("client_id");
-            clientSecret = request.getParameter("client_secret");
-        }
-
-        // 如果两者非空,则返回
-        if (StrUtil.isNotEmpty(clientId) && StrUtil.isNotEmpty(clientSecret)) {
-            return new String[]{clientId, clientSecret};
-        }
-        return null;
-    }
-
-    /**
-     * 向指定URL发送GET方法的请求
-     *
-     * @param url   发送请求的URL
-     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
-     * @return URL 所代表远程资源的响应结果
-     */
-    public static String sendGet(String url, String param) {
-        String result = "";
-        BufferedReader in = null;
-        try {
-            String urlNameString = url + "?" + param;
-            URL realUrl = new URL(urlNameString);
-            // 打开和URL之间的连接
-            URLConnection connection = realUrl.openConnection();
-            // 设置通用的请求属性
-            connection.setRequestProperty("accept", "*/*");
-            connection.setRequestProperty("connection", "Keep-Alive");
-            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
-
-            // 建立实际的连接
-            connection.connect();
-            // 获取所有响应头字段
-            Map<String, List<String>> map = connection.getHeaderFields();
-            // 遍历所有的响应头字段
-            for (String key : map.keySet()) {
-                System.out.println(key + "--->" + map.get(key));
-            }
-            // 定义 BufferedReader输入流来读取URL的响应
-            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
-            String line;
-            while ((line = in.readLine()) != null) {
-                result += line;
-            }
-        } catch (Exception e) {
-            System.out.println("发送GET请求出现异常!" + e);
-            e.printStackTrace();
-        }
-        // 使用finally块来关闭输入流
-        finally {
-            try {
-                if (in != null) {
-                    in.close();
-                }
-            } catch (Exception e2) {
-                e2.printStackTrace();
-            }
-        }
-        return result;
-    }
-
-    public static String sendGet(String url, Map<String, String> params, String authorization) {
-        String result = "";
-        BufferedReader in = null;
-        try {
-            StringBuilder sb = new StringBuilder();
-            sb.append(url);
-            if (!CollectionUtils.isEmpty(params)) {
-                sb.append("?");
-                params.forEach((k, v) -> {
-                    sb.append(k + "=" + v + "&");
-                });
-                sb.append("t=" + System.currentTimeMillis());
-            }
-            String urlNameString = sb.toString();
-            URL realUrl = new URL(urlNameString);
-            // 打开和URL之间的连接
-            URLConnection connection = realUrl.openConnection();
-            // 设置通用的请求属性
-            connection.setRequestProperty("Authorization", authorization);
-            connection.setRequestProperty("accept", "*/*");
-            connection.setRequestProperty("connection", "Keep-Alive");
-            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
-
-            // 建立实际的连接
-            connection.connect();
-            // 获取所有响应头字段
-            Map<String, List<String>> map = connection.getHeaderFields();
-            // 遍历所有的响应头字段
-            for (String key : map.keySet()) {
-                System.out.println(key + "--->" + map.get(key));
-            }
-            // 定义 BufferedReader输入流来读取URL的响应
-            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
-            String line;
-            while ((line = in.readLine()) != null) {
-                result += line;
-            }
-        } catch (Exception e) {
-            System.out.println("发送GET请求出现异常!" + e);
-            e.printStackTrace();
-        }
-        // 使用finally块来关闭输入流
-        finally {
-            try {
-                if (in != null) {
-                    in.close();
-                }
-            } catch (Exception e2) {
-                e2.printStackTrace();
-            }
-        }
-        return result;
-    }
-
-    /**
-     * 向指定 URL 发送POST方法的请求
-     *
-     * @param url
-     * @param json
-     * @return
-     */
-    public static String sendPost(String url, String json) {
-        PrintWriter out = null;
-        BufferedReader in = null;
-        String result = "";
-        try {
-            URL realUrl = new URL(url);
-            // 打开和URL之间的连接
-            URLConnection conn = realUrl.openConnection();
-            // 设置通用的请求属性
-            conn.setRequestProperty("content-type", "application/json");
-            conn.setRequestProperty("accept", "*/*");
-            conn.setRequestProperty("connection", "Keep-Alive");
-            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
-
-            // 发送POST请求必须设置如下两行
-            conn.setDoOutput(true);
-            conn.setDoInput(true);
-            // 获取URLConnection对象对应的输出流
-            out = new PrintWriter(conn.getOutputStream());
-            // 发送请求参数
-            out.print(json);
-            // flush输出流的缓冲
-            out.flush();
-            // 定义BufferedReader输入流来读取URL的响应
-            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
-            String line;
-            while ((line = in.readLine()) != null) {
-                result += line;
-            }
-        } catch (Exception e) {
-            System.out.println("发送 POST 请求出现异常!" + e);
-            e.printStackTrace();
-        }
-        //使用finally块来关闭输出流、输入流
-        finally {
-            try {
-                if (out != null) {
-                    out.close();
-                }
-                if (in != null) {
-                    in.close();
-                }
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        }
-        return result;
-    }
-
-    /**
-     * 向指定 URL 发送POST方法的请求
-     *
-     * @param url
-     * @param json
-     * @param authorization
-     * @return
-     */
-    public static String sendPost(String url, String json, String authorization) {
-        PrintWriter out = null;
-        BufferedReader in = null;
-        String result = "";
-        try {
-            URL realUrl = new URL(url);
-            // 打开和URL之间的连接
-            URLConnection conn = realUrl.openConnection();
-            // 设置通用的请求属性
-            conn.setRequestProperty("Authorization", authorization);
-            conn.setRequestProperty("accept", "*/*");
-            conn.setRequestProperty("connection", "Keep-Alive");
-            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
-
-            // 发送POST请求必须设置如下两行
-            conn.setDoOutput(true);
-            conn.setDoInput(true);
-            // 获取URLConnection对象对应的输出流
-            out = new PrintWriter(conn.getOutputStream());
-            // 发送请求参数
-            out.print(json);
-            // flush输出流的缓冲
-            out.flush();
-            // 定义BufferedReader输入流来读取URL的响应
-            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
-            String line;
-            while ((line = in.readLine()) != null) {
-                result += line;
-            }
-        } catch (Exception e) {
-            System.out.println("发送 POST 请求出现异常!" + e);
-            e.printStackTrace();
-        }
-        //使用finally块来关闭输出流、输入流
-        finally {
-            try {
-                if (out != null) {
-                    out.close();
-                }
-                if (in != null) {
-                    in.close();
-                }
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }
-        }
-        return result;
-    }
-
-    public static String sendPostToken(String url, String json, String authorization) {
-        String result = "";
-        try {
-            URL realUrl = new URL(url);
-            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
-            connection.setRequestMethod("POST");
-            connection.setRequestProperty("Content-Type", "application/json");
-            connection.setRequestProperty("Authorization", authorization);
-            connection.setDoOutput(true);
-
-            // 发送POST请求的数据
-            try (OutputStream os = connection.getOutputStream()) {
-                os.write(json.getBytes());
-                os.flush();
-            }
-            // 获取响应码和响应体
-            int responseCode = connection.getResponseCode();
-            if (responseCode == HttpURLConnection.HTTP_OK) { // 200 OK
-                try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
-                    StringBuilder response = new StringBuilder();
-                    String responseLine;
-                    while ((responseLine = br.readLine()) != null) {
-                        response.append(responseLine.trim());
-                    }
-                    result = response.toString();
-                }
-            } else {
-                System.out.println("POST request not worked");
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return result;
-    }
-
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/io/FileUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/io/FileUtils.java
deleted file mode 100644
index 5356e90..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/io/FileUtils.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.iailab.framework.common.util.io;
-
-import cn.hutool.core.io.FileTypeUtil;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.file.FileNameUtil;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.digest.DigestUtil;
-import lombok.SneakyThrows;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-
-/**
- * 文件工具类
- *
- * @author iailab
- */
-public class FileUtils {
-
-    /**
-     * 创建临时文件
-     * 该文件会在 JVM 退出时,进行删除
-     *
-     * @param data 文件内容
-     * @return 文件
-     */
-    @SneakyThrows
-    public static File createTempFile(String data) {
-        File file = createTempFile();
-        // 写入内容
-        FileUtil.writeUtf8String(data, file);
-        return file;
-    }
-
-    /**
-     * 创建临时文件
-     * 该文件会在 JVM 退出时,进行删除
-     *
-     * @param data 文件内容
-     * @return 文件
-     */
-    @SneakyThrows
-    public static File createTempFile(byte[] data) {
-        File file = createTempFile();
-        // 写入内容
-        FileUtil.writeBytes(data, file);
-        return file;
-    }
-
-    /**
-     * 创建临时文件,无内容
-     * 该文件会在 JVM 退出时,进行删除
-     *
-     * @return 文件
-     */
-    @SneakyThrows
-    public static File createTempFile() {
-        // 创建文件,通过 UUID 保证唯一
-        File file = File.createTempFile(IdUtil.simpleUUID(), null);
-        // 标记 JVM 退出时,自动删除
-        file.deleteOnExit();
-        return file;
-    }
-
-    /**
-     * 生成文件路径
-     *
-     * @param content      文件内容
-     * @param originalName 原始文件名
-     * @return path,唯一不可重复
-     */
-    public static String generatePath(byte[] content, String originalName) {
-        String sha256Hex = DigestUtil.sha256Hex(content);
-        // 情况一:如果存在 name,则优先使用 name 的后缀
-        if (StrUtil.isNotBlank(originalName)) {
-            String extName = FileNameUtil.extName(originalName);
-            return StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName;
-        }
-        // 情况二:基于 content 计算
-        return sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content));
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/io/IoUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/io/IoUtils.java
deleted file mode 100644
index be1d14c..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/io/IoUtils.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.common.util.io;
-
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.StrUtil;
-
-import java.io.InputStream;
-
-/**
- * IO 工具类,用于 {@link cn.hutool.core.io.IoUtil} 缺失的方法
- *
- * @author iailab
- */
-public class IoUtils {
-
-    /**
-     * 从流中读取 UTF8 编码的内容
-     *
-     * @param in 输入流
-     * @param isClose 是否关闭
-     * @return 内容
-     * @throws IORuntimeException IO 异常
-     */
-    public static String readUtf8(InputStream in, boolean isClose) throws IORuntimeException {
-        return StrUtil.utf8Str(IoUtil.read(in, isClose));
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/JsonUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/JsonUtils.java
deleted file mode 100644
index 88e56cd..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/JsonUtils.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package com.iailab.framework.common.util.json;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONUtil;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.IOException;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * JSON 工具类
- *
- * @author iailab
- */
-@Slf4j
-public class JsonUtils {
-
-    private static ObjectMapper objectMapper = new ObjectMapper();
-
-    static {
-        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
-        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
-        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
-        objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
-    }
-
-    /**
-     * 初始化 objectMapper 属性
-     * <p>
-     * 通过这样的方式,使用 Spring 创建的 ObjectMapper Bean
-     *
-     * @param objectMapper ObjectMapper 对象
-     */
-    public static void init(ObjectMapper objectMapper) {
-        JsonUtils.objectMapper = objectMapper;
-    }
-
-    @SneakyThrows
-    public static String toJsonString(Object object) {
-        return objectMapper.writeValueAsString(object);
-    }
-
-    @SneakyThrows
-    public static byte[] toJsonByte(Object object) {
-        return objectMapper.writeValueAsBytes(object);
-    }
-
-    @SneakyThrows
-    public static String toJsonPrettyString(Object object) {
-        return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
-    }
-
-    public static <T> T parseObject(String text, Class<T> clazz) {
-        if (StrUtil.isEmpty(text)) {
-            return null;
-        }
-        try {
-            return objectMapper.readValue(text, clazz);
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> T parseObject(String text, String path, Class<T> clazz) {
-        if (StrUtil.isEmpty(text)) {
-            return null;
-        }
-        try {
-            JsonNode treeNode = objectMapper.readTree(text);
-            JsonNode pathNode = treeNode.path(path);
-            return objectMapper.readValue(pathNode.toString(), clazz);
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> T parseObject(String text, Type type) {
-        if (StrUtil.isEmpty(text)) {
-            return null;
-        }
-        try {
-            return objectMapper.readValue(text, objectMapper.getTypeFactory().constructType(type));
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * 将字符串解析成指定类型的对象
-     * 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下,
-     * 如果 text 没有 class 属性,则会报错。此时,使用这个方法,可以解决。
-     *
-     * @param text 字符串
-     * @param clazz 类型
-     * @return 对象
-     */
-    public static <T> T parseObject2(String text, Class<T> clazz) {
-        if (StrUtil.isEmpty(text)) {
-            return null;
-        }
-        return JSONUtil.toBean(text, clazz);
-    }
-
-    public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
-        if (ArrayUtil.isEmpty(bytes)) {
-            return null;
-        }
-        try {
-            return objectMapper.readValue(bytes, clazz);
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", bytes, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> T parseObject(String text, TypeReference<T> typeReference) {
-        try {
-            return objectMapper.readValue(text, typeReference);
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * 解析 JSON 字符串成指定类型的对象,如果解析失败,则返回 null
-     *
-     * @param text 字符串
-     * @param typeReference 类型引用
-     * @return 指定类型的对象
-     */
-    public static <T> T parseObjectQuietly(String text, TypeReference<T> typeReference) {
-        try {
-            return objectMapper.readValue(text, typeReference);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    public static <T> List<T> parseArray(String text, Class<T> clazz) {
-        if (StrUtil.isEmpty(text)) {
-            return new ArrayList<>();
-        }
-        try {
-            return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> List<T> parseArray(String text, String path, Class<T> clazz) {
-        if (StrUtil.isEmpty(text)) {
-            return null;
-        }
-        try {
-            JsonNode treeNode = objectMapper.readTree(text);
-            JsonNode pathNode = treeNode.path(path);
-            return objectMapper.readValue(pathNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static JsonNode parseTree(String text) {
-        try {
-            return objectMapper.readTree(text);
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static JsonNode parseTree(byte[] text) {
-        try {
-            return objectMapper.readTree(text);
-        } catch (IOException e) {
-            log.error("json parse err,json:{}", text, e);
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static boolean isJson(String text) {
-        return JSONUtil.isTypeJSON(text);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/NumberSerializer.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/NumberSerializer.java
deleted file mode 100644
index 19d0591..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/NumberSerializer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.iailab.framework.common.util.json.databind;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-
-import java.io.IOException;
-
-/**
- * Long 序列化规则
- *
- * 会将超长 long 值转换为 string,解决前端 JavaScript 最大安全整数是 2^53-1 的问题
- *
- * @author 星语
- */
-@JacksonStdImpl
-public class NumberSerializer extends com.fasterxml.jackson.databind.ser.std.NumberSerializer {
-
-    private static final long MAX_SAFE_INTEGER = 9007199254740991L;
-    private static final long MIN_SAFE_INTEGER = -9007199254740991L;
-
-    public static final NumberSerializer INSTANCE = new NumberSerializer(Number.class);
-
-    public NumberSerializer(Class<? extends Number> rawType) {
-        super(rawType);
-    }
-
-    @Override
-    public void serialize(Number value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
-        // 超出范围 序列化位字符串
-        if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
-            super.serialize(value, gen, serializers);
-        } else {
-            gen.writeString(value.toString());
-        }
-    }
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/TimestampLocalDateTimeDeserializer.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/TimestampLocalDateTimeDeserializer.java
deleted file mode 100644
index d024c92..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/TimestampLocalDateTimeDeserializer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.iailab.framework.common.util.json.databind;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-
-/**
- * 基于时间戳的 LocalDateTime 反序列化器
- *
- * @author 老五
- */
-public class TimestampLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
-
-    public static final TimestampLocalDateTimeDeserializer INSTANCE = new TimestampLocalDateTimeDeserializer();
-
-    @Override
-    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
-        // 将 Long 时间戳,转换为 LocalDateTime 对象
-        return LocalDateTime.ofInstant(Instant.ofEpochMilli(p.getValueAsLong()), ZoneId.systemDefault());
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java
deleted file mode 100644
index 6d43528..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.iailab.framework.common.util.json.databind;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-
-/**
- * 基于时间戳的 LocalDateTime 序列化器
- *
- * @author 老五
- */
-public class TimestampLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
-
-    public static final TimestampLocalDateTimeSerializer INSTANCE = new TimestampLocalDateTimeSerializer();
-
-    @Override
-    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
-        // 将 LocalDateTime 对象,转换为 Long 时间戳
-        gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/monitor/TracerUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/monitor/TracerUtils.java
deleted file mode 100644
index e285d44..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/monitor/TracerUtils.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.framework.common.util.monitor;
-
-import org.apache.skywalking.apm.toolkit.trace.TraceContext;
-
-/**
- * 链路追踪工具类
- *
- * 考虑到每个 starter 都需要用到该工具类,所以放到 common 模块下的 util 包下
- *
- * @author iailab
- */
-public class TracerUtils {
-
-    /**
-     * 私有化构造方法
-     */
-    private TracerUtils() {
-    }
-
-    /**
-     * 获得链路追踪编号,直接返回 SkyWalking 的 TraceId。
-     * 如果不存在的话为空字符串!!!
-     *
-     * @return 链路追踪编号
-     */
-    public static String getTraceId() {
-        return TraceContext.traceId();
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/number/MoneyUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/number/MoneyUtils.java
deleted file mode 100644
index eb435b7..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/number/MoneyUtils.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.iailab.framework.common.util.number;
-
-import cn.hutool.core.math.Money;
-import cn.hutool.core.util.NumberUtil;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-
-/**
- * 金额工具类
- *
- * @author iailab
- */
-public class MoneyUtils {
-
-    /**
-     * 金额的小数位数
-     */
-    private static final int PRICE_SCALE = 2;
-
-    /**
-     * 百分比对应的 BigDecimal 对象
-     */
-    public static final BigDecimal PERCENT_100 = BigDecimal.valueOf(100);
-
-    /**
-     * 计算百分比金额,四舍五入
-     *
-     * @param price 金额
-     * @param rate  百分比,例如说 56.77% 则传入 56.77
-     * @return 百分比金额
-     */
-    public static Integer calculateRatePrice(Integer price, Double rate) {
-        return calculateRatePrice(price, rate, 0, RoundingMode.HALF_UP).intValue();
-    }
-
-    /**
-     * 计算百分比金额,向下传入
-     *
-     * @param price 金额
-     * @param rate  百分比,例如说 56.77% 则传入 56.77
-     * @return 百分比金额
-     */
-    public static Integer calculateRatePriceFloor(Integer price, Double rate) {
-        return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue();
-    }
-
-    /**
-     * 计算百分比金额
-     *
-     * @param price   金额(单位分)
-     * @param count   数量
-     * @param percent 折扣(单位分),列如 60.2%,则传入 6020
-     * @return 商品总价
-     */
-    public static Integer calculator(Integer price, Integer count, Integer percent) {
-        price = price * count;
-        if (percent == null) {
-            return price;
-        }
-        return MoneyUtils.calculateRatePriceFloor(price, (double) (percent / 100));
-    }
-
-    /**
-     * 计算百分比金额
-     *
-     * @param price        金额
-     * @param rate         百分比,例如说 56.77% 则传入 56.77
-     * @param scale        保留小数位数
-     * @param roundingMode 舍入模式
-     */
-    public static BigDecimal calculateRatePrice(Number price, Number rate, int scale, RoundingMode roundingMode) {
-        return NumberUtil.toBigDecimal(price).multiply(NumberUtil.toBigDecimal(rate)) // 乘以
-                .divide(BigDecimal.valueOf(100), scale, roundingMode); // 除以 100
-    }
-
-    /**
-     * 分转元
-     *
-     * @param fen 分
-     * @return 元
-     */
-    public static BigDecimal fenToYuan(int fen) {
-        return new Money(0, fen).getAmount();
-    }
-
-    /**
-     * 分转元(字符串)
-     *
-     * 例如说 fen 为 1 时,则结果为 0.01
-     *
-     * @param fen 分
-     * @return 元
-     */
-    public static String fenToYuanStr(int fen) {
-        return new Money(0, fen).toString();
-    }
-
-    /**
-     * 金额相乘,默认进行四舍五入
-     *
-     * 位数:{@link #PRICE_SCALE}
-     *
-     * @param price 金额
-     * @param count 数量
-     * @return 金额相乘结果
-     */
-    public static BigDecimal priceMultiply(BigDecimal price, BigDecimal count) {
-        if (price == null || count == null) {
-            return null;
-        }
-        return price.multiply(count).setScale(PRICE_SCALE, RoundingMode.HALF_UP);
-    }
-
-    /**
-     * 金额相乘(百分比),默认进行四舍五入
-     *
-     * 位数:{@link #PRICE_SCALE}
-     *
-     * @param price  金额
-     * @param percent 百分比
-     * @return 金额相乘结果
-     */
-    public static BigDecimal priceMultiplyPercent(BigDecimal price, BigDecimal percent) {
-        if (price == null || percent == null) {
-            return null;
-        }
-        return price.multiply(percent).divide(PERCENT_100, PRICE_SCALE, RoundingMode.HALF_UP);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/number/NumberUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/number/NumberUtils.java
deleted file mode 100644
index f45f673..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/number/NumberUtils.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.iailab.framework.common.util.number;
-
-import cn.hutool.core.util.NumberUtil;
-import cn.hutool.core.util.StrUtil;
-
-import java.math.BigDecimal;
-
-/**
- * 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能
- *
- * @author iailab
- */
-public class NumberUtils {
-
-    public static Long parseLong(String str) {
-        return StrUtil.isNotEmpty(str) ? Long.valueOf(str) : null;
-    }
-
-    public static Integer parseInt(String str) {
-        return StrUtil.isNotEmpty(str) ? Integer.valueOf(str) : null;
-    }
-
-    /**
-     * 通过经纬度获取地球上两点之间的距离
-     *
-     * 参考 <<a href="https://gitee.com/dromara/hutool/blob/1caabb586b1f95aec66a21d039c5695df5e0f4c1/hutool-core/src/main/java/cn/hutool/core/util/DistanceUtil.java">DistanceUtil</a>> 实现,目前它已经被 hutool 删除
-     *
-     * @param lat1 经度1
-     * @param lng1 纬度1
-     * @param lat2 经度2
-     * @param lng2 纬度2
-     * @return 距离,单位:千米
-     */
-    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
-        double radLat1 = lat1 * Math.PI / 180.0;
-        double radLat2 = lat2 * Math.PI / 180.0;
-        double a = radLat1 - radLat2;
-        double b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
-        double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
-                + Math.cos(radLat1) * Math.cos(radLat2)
-                * Math.pow(Math.sin(b / 2), 2)));
-        distance = distance * 6378.137;
-        distance = Math.round(distance * 10000d) / 10000d;
-        return distance;
-    }
-
-    /**
-     * 提供精确的乘法运算
-     *
-     * 和 hutool {@link NumberUtil#mul(BigDecimal...)} 的差别是,如果存在 null,则返回 null
-     *
-     * @param values 多个被乘值
-     * @return 积
-     */
-    public static BigDecimal mul(BigDecimal... values) {
-        for (BigDecimal value : values) {
-            if (value == null) {
-                return null;
-            }
-        }
-        return NumberUtil.mul(values);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/BeanUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/BeanUtils.java
deleted file mode 100644
index 80c1beb..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/BeanUtils.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.iailab.framework.common.util.object;
-
-import cn.hutool.core.bean.BeanUtil;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.collection.CollectionUtils;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * Bean 工具类
- *
- * 1. 默认使用 {@link cn.hutool.core.bean.BeanUtil} 作为实现类,虽然不同 bean 工具的性能有差别,但是对绝大多数同学的项目,不用在意这点性能
- * 2. 针对复杂的对象转换,可以搜参考 AuthConvert 实现,通过 mapstruct + default 配合实现
- *
- * @author iailab
- */
-public class BeanUtils {
-
-    public static <T> T toBean(Object source, Class<T> targetClass) {
-        return BeanUtil.toBean(source, targetClass);
-    }
-
-    public static <T> T toBean(Object source, Class<T> targetClass, Consumer<T> peek) {
-        T target = toBean(source, targetClass);
-        if (target != null) {
-            peek.accept(target);
-        }
-        return target;
-    }
-
-    public static <S, T> List<T> toBean(List<S> source, Class<T> targetType) {
-        if (source == null) {
-            return null;
-        }
-        return CollectionUtils.convertList(source, s -> toBean(s, targetType));
-    }
-
-    public static <S, T> List<T> toBean(List<S> source, Class<T> targetType, Consumer<T> peek) {
-        List<T> list = toBean(source, targetType);
-        if (list != null) {
-            list.forEach(peek);
-        }
-        return list;
-    }
-
-    public static <S, T> PageResult<T> toBean(PageResult<S> source, Class<T> targetType) {
-        return toBean(source, targetType, null);
-    }
-
-    public static <S, T> PageResult<T> toBean(PageResult<S> source, Class<T> targetType, Consumer<T> peek) {
-        if (source == null) {
-            return null;
-        }
-        List<T> list = toBean(source.getList(), targetType);
-        if (peek != null) {
-            list.forEach(peek);
-        }
-        return new PageResult<>(list, source.getTotal());
-    }
-
-    public static void copyProperties(Object source, Object target) {
-        if (source == null || target == null) {
-            return;
-        }
-        BeanUtil.copyProperties(source, target, false);
-    }
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/ConvertUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/ConvertUtils.java
deleted file mode 100644
index 4faad98..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/ConvertUtils.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.util.object;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 转换工具类
- *
- * @author Mark sunlightcs@gmail.com
- */
-public class ConvertUtils {
-    private static Logger logger = LoggerFactory.getLogger(ConvertUtils.class);
-
-    public static <T> T sourceToTarget(Object source, Class<T> target){
-        if(source == null){
-            return null;
-        }
-        T targetObject = null;
-        try {
-            targetObject = target.newInstance();
-            BeanUtils.copyProperties(source, targetObject);
-        } catch (Exception e) {
-            logger.error("convert error ", e);
-        }
-
-        return targetObject;
-    }
-
-    public static <T> List<T> sourceToTarget(Collection<?> sourceList, Class<T> target){
-        if(sourceList == null){
-            return null;
-        }
-
-        List targetList = new ArrayList<>(sourceList.size());
-        try {
-            for(Object source : sourceList){
-                T targetObject = target.newInstance();
-                BeanUtils.copyProperties(source, targetObject);
-                targetList.add(targetObject);
-            }
-        }catch (Exception e){
-            logger.error("convert error ", e);
-        }
-
-        return targetList;
-    }
-    /**
-     * 获取类的所有属性,包括父类
-     *
-     * @param object
-     * @return
-     */
-    public static Field[] getAllFields(Object object) {
-        Class<?> clazz = object.getClass();
-        List<Field> fieldList = new ArrayList<>();
-        while (clazz != null) {
-            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
-            clazz = clazz.getSuperclass();
-        }
-        Field[] fields = new Field[fieldList.size()];
-        fieldList.toArray(fields);
-        return fields;
-    }
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/ObjectUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/ObjectUtils.java
deleted file mode 100644
index 728287e..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/ObjectUtils.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.iailab.framework.common.util.object;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.ReflectUtil;
-
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.function.Consumer;
-
-/**
- * Object 工具类
- *
- * @author iailab
- */
-public class ObjectUtils {
-
-    /**
-     * 复制对象,并忽略 Id 编号
-     *
-     * @param object 被复制对象
-     * @param consumer 消费者,可以二次编辑被复制对象
-     * @return 复制后的对象
-     */
-    public static <T> T cloneIgnoreId(T object, Consumer<T> consumer) {
-        T result = ObjectUtil.clone(object);
-        // 忽略 id 编号
-        Field field = ReflectUtil.getField(object.getClass(), "id");
-        if (field != null) {
-            ReflectUtil.setFieldValue(result, field, null);
-        }
-        // 二次编辑
-        if (result != null) {
-            consumer.accept(result);
-        }
-        return result;
-    }
-
-    public static <T extends Comparable<T>> T max(T obj1, T obj2) {
-        if (obj1 == null) {
-            return obj2;
-        }
-        if (obj2 == null) {
-            return obj1;
-        }
-        return obj1.compareTo(obj2) > 0 ? obj1 : obj2;
-    }
-
-    @SafeVarargs
-    public static <T> T defaultIfNull(T... array) {
-        for (T item : array) {
-            if (item != null) {
-                return item;
-            }
-        }
-        return null;
-    }
-
-    @SafeVarargs
-    public static <T> boolean equalsAny(T obj, T... array) {
-        return Arrays.asList(array).contains(obj);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/PageUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/PageUtils.java
deleted file mode 100644
index 3476b90..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/object/PageUtils.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.iailab.framework.common.util.object;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.func.Func1;
-import cn.hutool.core.lang.func.LambdaUtil;
-import cn.hutool.core.util.ArrayUtil;
-import com.iailab.framework.common.pojo.PageParam;
-import com.iailab.framework.common.pojo.SortablePageParam;
-import com.iailab.framework.common.pojo.SortingField;
-import org.springframework.util.Assert;
-
-import static java.util.Collections.singletonList;
-
-/**
- * {@link com.iailab.framework.common.pojo.PageParam} 工具类
- *
- * @author iailab
- */
-public class PageUtils {
-
-    private static final Object[] ORDER_TYPES = new String[]{SortingField.ORDER_ASC, SortingField.ORDER_DESC};
-
-    public static int getStart(PageParam pageParam) {
-        return (pageParam.getPageNo() - 1) * pageParam.getPageSize();
-    }
-
-    /**
-     * 构建排序字段(默认倒序)
-     *
-     * @param func 排序字段的 Lambda 表达式
-     * @param <T>  排序字段所属的类型
-     * @return 排序字段
-     */
-    public static <T> SortingField buildSortingField(Func1<T, ?> func) {
-        return buildSortingField(func, SortingField.ORDER_DESC);
-    }
-
-    /**
-     * 构建排序字段
-     *
-     * @param func  排序字段的 Lambda 表达式
-     * @param order 排序类型 {@link SortingField#ORDER_ASC} {@link SortingField#ORDER_DESC}
-     * @param <T>   排序字段所属的类型
-     * @return 排序字段
-     */
-    public static <T> SortingField buildSortingField(Func1<T, ?> func, String order) {
-        Assert.isTrue(ArrayUtil.contains(ORDER_TYPES, order), String.format("字段的排序类型只能是 %s/%s", ORDER_TYPES));
-
-        String fieldName = LambdaUtil.getFieldName(func);
-        return new SortingField(fieldName, order);
-    }
-
-    /**
-     * 构建默认的排序字段
-     * 如果排序字段为空,则设置排序字段;否则忽略
-     *
-     * @param sortablePageParam 排序分页查询参数
-     * @param func              排序字段的 Lambda 表达式
-     * @param <T>               排序字段所属的类型
-     */
-    public static <T> void buildDefaultSortingField(SortablePageParam sortablePageParam, Func1<T, ?> func) {
-        if (sortablePageParam != null && CollUtil.isEmpty(sortablePageParam.getSortingFields())) {
-            sortablePageParam.setSortingFields(singletonList(buildSortingField(func)));
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/package-info.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/package-info.java
deleted file mode 100644
index 74c17a4..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/package-info.java
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * 对于工具类的选择,优先查找 Hutool 中有没对应的方法
- * 如果没有,则自己封装对应的工具类,以 Utils 结尾,用于区分
- *
- * ps:如果担心 Hutool 存在坑的问题,可以阅读 Hutool 的实现源码,以确保可靠性。并且,可以补充相关的单元测试。
- */
-package com.iailab.framework.common.util;
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/servlet/ServletUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/servlet/ServletUtils.java
deleted file mode 100644
index 7f12b67..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/servlet/ServletUtils.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.iailab.framework.common.util.servlet;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.extra.servlet.ServletUtil;
-import com.iailab.framework.common.util.json.JsonUtils;
-import org.springframework.http.MediaType;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.net.URLEncoder;
-import java.util.Map;
-
-/**
- * 客户端工具类
- *
- * @author iailab
- */
-public class ServletUtils {
-
-    /**
-     * 返回 JSON 字符串
-     *
-     * @param response 响应
-     * @param object   对象,会序列化成 JSON 字符串
-     */
-    @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
-    public static void writeJSON(HttpServletResponse response, Object object) {
-        String content = JsonUtils.toJsonString(object);
-        ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
-    }
-
-    /**
-     * 返回附件
-     *
-     * @param response 响应
-     * @param filename 文件名
-     * @param content  附件内容
-     */
-    public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
-        // 设置 header 和 contentType
-        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
-        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
-        // 输出附件
-        IoUtil.write(response.getOutputStream(), false, content);
-    }
-
-    /**
-     * @param request 请求
-     * @return ua
-     */
-    public static String getUserAgent(HttpServletRequest request) {
-        String ua = request.getHeader("User-Agent");
-        return ua != null ? ua : "";
-    }
-
-    /**
-     * 获得请求
-     *
-     * @return HttpServletRequest
-     */
-    public static HttpServletRequest getRequest() {
-        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
-        if (!(requestAttributes instanceof ServletRequestAttributes)) {
-            return null;
-        }
-        return ((ServletRequestAttributes) requestAttributes).getRequest();
-    }
-
-    public static String getUserAgent() {
-        HttpServletRequest request = getRequest();
-        if (request == null) {
-            return null;
-        }
-        return getUserAgent(request);
-    }
-
-    public static String getClientIP() {
-        HttpServletRequest request = getRequest();
-        if (request == null) {
-            return null;
-        }
-        return ServletUtil.getClientIP(request);
-    }
-
-    public static boolean isJsonRequest(ServletRequest request) {
-        return StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE);
-    }
-
-    public static String getBody(HttpServletRequest request) {
-        // 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
-        if (isJsonRequest(request)) {
-            return ServletUtil.getBody(request);
-        }
-        return null;
-    }
-
-    public static byte[] getBodyBytes(HttpServletRequest request) {
-        // 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
-        if (isJsonRequest(request)) {
-            return ServletUtil.getBodyBytes(request);
-        }
-        return null;
-    }
-
-    public static String getClientIP(HttpServletRequest request) {
-        return ServletUtil.getClientIP(request);
-    }
-
-    public static Map<String, String> getParamMap(HttpServletRequest request) {
-        return ServletUtil.getParamMap(request);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringContextUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringContextUtils.java
deleted file mode 100644
index 1cc4391..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringContextUtils.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.util.spring;
-
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.stereotype.Component;
-
-/**
- * Spring Context 工具类
- * 
- * @author Mark sunlightcs@gmail.com
- */
-@Component
-public class SpringContextUtils implements ApplicationContextAware {
-	public static ApplicationContext applicationContext; 
-
-	@Override
-	public void setApplicationContext(ApplicationContext applicationContext)
-			throws BeansException {
-		SpringContextUtils.applicationContext = applicationContext;
-	}
-
-	public static Object getBean(String name) {
-		return applicationContext.getBean(name);
-	}
-
-	public static <T> T getBean(Class<T> requiredType) {
-		return applicationContext.getBean(requiredType);
-	}
-
-	public static <T> T getBean(String name, Class<T> requiredType) {
-		return applicationContext.getBean(name, requiredType);
-	}
-
-	public static boolean containsBean(String name) {
-		return applicationContext.containsBean(name);
-	}
-
-	public static boolean isSingleton(String name) {
-		return applicationContext.isSingleton(name);
-	}
-
-	public static Class<? extends Object> getType(String name) {
-		return applicationContext.getType(name);
-	}
-
-}
\ No newline at end of file
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringExpressionUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringExpressionUtils.java
deleted file mode 100644
index 9302a86..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringExpressionUtils.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.iailab.framework.common.util.spring;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ArrayUtil;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.springframework.core.DefaultParameterNameDiscoverer;
-import org.springframework.core.ParameterNameDiscoverer;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
-
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Spring EL 表达式的工具类
- *
- * @author mashu
- */
-public class SpringExpressionUtils {
-
-    /**
-     * Spring EL 表达式解析器
-     */
-    private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
-    /**
-     * 参数名发现器
-     */
-    private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
-
-    private SpringExpressionUtils() {
-    }
-
-    /**
-     * 从切面中,单个解析 EL 表达式的结果
-     *
-     * @param joinPoint        切面点
-     * @param expressionString EL 表达式数组
-     * @return 执行界面
-     */
-    public static Object parseExpression(JoinPoint joinPoint, String expressionString) {
-        Map<String, Object> result = parseExpressions(joinPoint, Collections.singletonList(expressionString));
-        return result.get(expressionString);
-    }
-
-    /**
-     * 从切面中,批量解析 EL 表达式的结果
-     *
-     * @param joinPoint         切面点
-     * @param expressionStrings EL 表达式数组
-     * @return 结果,key 为表达式,value 为对应值
-     */
-    public static Map<String, Object> parseExpressions(JoinPoint joinPoint, List<String> expressionStrings) {
-        // 如果为空,则不进行解析
-        if (CollUtil.isEmpty(expressionStrings)) {
-            return MapUtil.newHashMap();
-        }
-
-        // 第一步,构建解析的上下文 EvaluationContext
-        // 通过 joinPoint 获取被注解方法
-        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
-        Method method = methodSignature.getMethod();
-        // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组
-        String[] paramNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method);
-        // Spring 的表达式上下文对象
-        EvaluationContext context = new StandardEvaluationContext();
-        // 给上下文赋值
-        if (ArrayUtil.isNotEmpty(paramNames)) {
-            Object[] args = joinPoint.getArgs();
-            for (int i = 0; i < paramNames.length; i++) {
-                context.setVariable(paramNames[i], args[i]);
-            }
-        }
-
-        // 第二步,逐个参数解析
-        Map<String, Object> result = MapUtil.newHashMap(expressionStrings.size(), true);
-        expressionStrings.forEach(key -> {
-            Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context);
-            result.put(key, value);
-        });
-        return result;
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringUtils.java
deleted file mode 100644
index 00ca53b..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/spring/SpringUtils.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.iailab.framework.common.util.spring;
-
-import cn.hutool.extra.spring.SpringUtil;
-
-import java.util.Objects;
-
-/**
- * Spring 工具类
- *
- * @author iailab
- */
-public class SpringUtils extends SpringUtil {
-
-    /**
-     * 是否为生产环境
-     *
-     * @return 是否生产环境
-     */
-    public static boolean isProd() {
-        String activeProfile = getActiveProfile();
-        return Objects.equals("prod", activeProfile);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/string/StrUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/string/StrUtils.java
deleted file mode 100644
index 31e2c4c..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/string/StrUtils.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.iailab.framework.common.util.string;
-
-import cn.hutool.core.text.StrPool;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.StrUtil;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * 字符串工具类
- *
- * @author iailab
- */
-public class StrUtils {
-
-    public static String maxLength(CharSequence str, int maxLength) {
-        return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好
-    }
-
-    /**
-     * 给定字符串是否以任何一个字符串开始
-     * 给定字符串和数组为空都返回 false
-     *
-     * @param str      给定字符串
-     * @param prefixes 需要检测的开始字符串
-     * @since 3.0.6
-     */
-    public static boolean startWithAny(String str, Collection<String> prefixes) {
-        if (StrUtil.isEmpty(str) || ArrayUtil.isEmpty(prefixes)) {
-            return false;
-        }
-
-        for (CharSequence suffix : prefixes) {
-            if (StrUtil.startWith(str, suffix, false)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static List<Long> splitToLong(String value, CharSequence separator) {
-        long[] longs = StrUtil.splitToLong(value, separator);
-        return Arrays.stream(longs).boxed().collect(Collectors.toList());
-    }
-
-    public static Set<Long> splitToLongSet(String value) {
-        return splitToLongSet(value, StrPool.COMMA);
-    }
-
-    public static Set<Long> splitToLongSet(String value, CharSequence separator) {
-        long[] longs = StrUtil.splitToLong(value, separator);
-        return Arrays.stream(longs).boxed().collect(Collectors.toSet());
-    }
-
-    public static List<Integer> splitToInteger(String value, CharSequence separator) {
-        int[] integers = StrUtil.splitToInt(value, separator);
-        return Arrays.stream(integers).boxed().collect(Collectors.toList());
-    }
-
-    /**
-     * 移除字符串中,包含指定字符串的行
-     *
-     * @param content 字符串
-     * @param sequence 包含的字符串
-     * @return 移除后的字符串
-     */
-    public static String removeLineContains(String content, String sequence) {
-        if (StrUtil.isEmpty(content) || StrUtil.isEmpty(sequence)) {
-            return content;
-        }
-        return Arrays.stream(content.split("\n"))
-                .filter(line -> !line.contains(sequence))
-                .collect(Collectors.joining("\n"));
-    }
-
-    /**
-     * 判断字符串是不是数字
-     *
-     * @param str
-     * @return
-     */
-    public static boolean isNumeric(String str) {
-        return str.matches("-?\\d+(\\.\\d+)?");
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/validation/ValidationUtils.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/validation/ValidationUtils.java
deleted file mode 100644
index d798b49..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/validation/ValidationUtils.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.iailab.framework.common.util.validation;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Assert;
-import org.springframework.util.StringUtils;
-
-import javax.validation.ConstraintViolation;
-import javax.validation.ConstraintViolationException;
-import javax.validation.Validation;
-import javax.validation.Validator;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-/**
- * 校验工具类
- *
- * @author iailab
- */
-public class ValidationUtils {
-
-    private static final Pattern PATTERN_MOBILE = Pattern.compile("^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[0,1,4-9])|(?:5[0-3,5-9])|(?:6[2,5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[0-3,5-9]))\\d{8}$");
-
-    private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");
-
-    private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*");
-
-    public static boolean isMobile(String mobile) {
-        return StringUtils.hasText(mobile)
-                && PATTERN_MOBILE.matcher(mobile).matches();
-    }
-
-    public static boolean isURL(String url) {
-        return StringUtils.hasText(url)
-                && PATTERN_URL.matcher(url).matches();
-    }
-
-    public static boolean isXmlNCName(String str) {
-        return StringUtils.hasText(str)
-                && PATTERN_XML_NCNAME.matcher(str).matches();
-    }
-
-    public static void validate(Object object, Class<?>... groups) {
-        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
-        Assert.notNull(validator);
-        validate(validator, object, groups);
-    }
-
-    public static void validate(Validator validator, Object object, Class<?>... groups) {
-        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
-        if (CollUtil.isNotEmpty(constraintViolations)) {
-            throw new ConstraintViolationException(constraintViolations);
-        }
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnum.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnum.java
deleted file mode 100644
index d7bc460..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnum.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import com.iailab.framework.common.core.IntArrayValuable;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.*;
-
-@Target({
-        ElementType.METHOD,
-        ElementType.FIELD,
-        ElementType.ANNOTATION_TYPE,
-        ElementType.CONSTRUCTOR,
-        ElementType.PARAMETER,
-        ElementType.TYPE_USE
-})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Constraint(
-        validatedBy = {InEnumValidator.class, InEnumCollectionValidator.class}
-)
-public @interface InEnum {
-
-    /**
-     * @return 实现 EnumValuable 接口的
-     */
-    Class<? extends IntArrayValuable> value();
-
-    String message() default "必须在指定范围 {value}";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumCollectionValidator.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumCollectionValidator.java
deleted file mode 100644
index ce162b2..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumCollectionValidator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.core.IntArrayValuable;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class InEnumCollectionValidator implements ConstraintValidator<InEnum, Collection<Integer>> {
-
-    private List<Integer> values;
-
-    @Override
-    public void initialize(InEnum annotation) {
-        IntArrayValuable[] values = annotation.value().getEnumConstants();
-        if (values.length == 0) {
-            this.values = Collections.emptyList();
-        } else {
-            this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
-        }
-    }
-
-    @Override
-    public boolean isValid(Collection<Integer> list, ConstraintValidatorContext context) {
-        // 校验通过
-        if (CollUtil.containsAll(values, list)) {
-            return true;
-        }
-        // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
-        context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
-        context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
-                .replaceAll("\\{value}", CollUtil.join(list, ","))).addConstraintViolation(); // 重新添加错误提示语句
-        return false;
-    }
-
-}
-
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumValidator.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumValidator.java
deleted file mode 100644
index f20b1fb..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/InEnumValidator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import com.iailab.framework.common.core.IntArrayValuable;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {
-
-    private List<Integer> values;
-
-    @Override
-    public void initialize(InEnum annotation) {
-        IntArrayValuable[] values = annotation.value().getEnumConstants();
-        if (values.length == 0) {
-            this.values = Collections.emptyList();
-        } else {
-            this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
-        }
-    }
-
-    @Override
-    public boolean isValid(Integer value, ConstraintValidatorContext context) {
-        // 为空时,默认不校验,即认为通过
-        if (value == null) {
-            return true;
-        }
-        // 校验通过
-        if (values.contains(value)) {
-            return true;
-        }
-        // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
-        context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
-        context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
-                .replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句
-        return false;
-    }
-
-}
-
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/Mobile.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/Mobile.java
deleted file mode 100644
index e1fedfd..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/Mobile.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.*;
-
-@Target({
-        ElementType.METHOD,
-        ElementType.FIELD,
-        ElementType.ANNOTATION_TYPE,
-        ElementType.CONSTRUCTOR,
-        ElementType.PARAMETER,
-        ElementType.TYPE_USE
-})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Constraint(
-        validatedBy = MobileValidator.class
-)
-public @interface Mobile {
-
-    String message() default "手机号格式不正确";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/MobileValidator.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/MobileValidator.java
deleted file mode 100644
index 1e0a24a..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/MobileValidator.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.util.validation.ValidationUtils;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-
-public class MobileValidator implements ConstraintValidator<Mobile, String> {
-
-    @Override
-    public void initialize(Mobile annotation) {
-    }
-
-    @Override
-    public boolean isValid(String value, ConstraintValidatorContext context) {
-        // 如果手机号为空,默认不校验,即校验通过
-        if (StrUtil.isEmpty(value)) {
-            return true;
-        }
-        // 校验手机
-        return ValidationUtils.isMobile(value);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/Telephone.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/Telephone.java
deleted file mode 100644
index ccc83e8..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/Telephone.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.*;
-
-@Target({
-        ElementType.METHOD,
-        ElementType.FIELD,
-        ElementType.ANNOTATION_TYPE,
-        ElementType.CONSTRUCTOR,
-        ElementType.PARAMETER,
-        ElementType.TYPE_USE
-})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Constraint(
-        validatedBy = TelephoneValidator.class
-)
-public @interface Telephone {
-
-    String message() default "电话格式不正确";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/TelephoneValidator.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/TelephoneValidator.java
deleted file mode 100644
index 42b3bfd..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/TelephoneValidator.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.framework.common.validation;
-
-import cn.hutool.core.text.CharSequenceUtil;
-import cn.hutool.core.util.PhoneUtil;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-
-public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
-
-    @Override
-    public void initialize(Telephone annotation) {
-    }
-
-    @Override
-    public boolean isValid(String value, ConstraintValidatorContext context) {
-        // 如果手机号为空,默认不校验,即校验通过
-        if (CharSequenceUtil.isEmpty(value)) {
-            return true;
-        }
-        // 校验手机
-        return PhoneUtil.isTel(value) || PhoneUtil.isPhone(value);
-    }
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/AddGroup.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/AddGroup.java
deleted file mode 100644
index a453fff..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/AddGroup.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.validation.group;
-
-/**
- * 新增 Group
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-public interface AddGroup {
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/DefaultGroup.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/DefaultGroup.java
deleted file mode 100644
index 895e477..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/DefaultGroup.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.validation.group;
-
-/**
- * 默认 Group
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-public interface DefaultGroup {
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/Group.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/Group.java
deleted file mode 100644
index ac31f90..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/Group.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.validation.group;
-
-import javax.validation.GroupSequence;
-
-/**
- * 定义校验顺序,如果AddGroup组失败,则UpdateGroup组不会再校验
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-@GroupSequence({AddGroup.class, UpdateGroup.class})
-public interface Group {
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/UpdateGroup.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/UpdateGroup.java
deleted file mode 100644
index 2ab7e74..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/group/UpdateGroup.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2018 人人开源 All rights reserved.
- *
- * https://www.renren.io
- *
- * 版权所有,侵权必究!
- */
-
-package com.iailab.framework.common.validation.group;
-
-/**
- * 修改 Group
- *
- * @author Mark sunlightcs@gmail.com
- * @since 1.0.0
- */
-public interface UpdateGroup {
-
-}
diff --git a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/package-info.java b/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/package-info.java
deleted file mode 100644
index 8fcc528..0000000
--- a/iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/validation/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 使用 Hibernate Validator 实现参数校验
- */
-package com.iailab.framework.common.validation;
diff --git a/iailab-framework/iailab-common/src/test/java/com/iailab/framework/common/util/collection/CollectionUtilsTest.java b/iailab-framework/iailab-common/src/test/java/com/iailab/framework/common/util/collection/CollectionUtilsTest.java
deleted file mode 100644
index 335e67c..0000000
--- a/iailab-framework/iailab-common/src/test/java/com/iailab/framework/common/util/collection/CollectionUtilsTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.iailab.framework.common.util.collection;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import org.junit.jupiter.api.Test;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.function.BiFunction;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * {@link CollectionUtils} 的单元测试
- */
-public class CollectionUtilsTest {
-
-    @Data
-    @AllArgsConstructor
-    private static class Dog {
-
-        private Integer id;
-        private String name;
-        private String code;
-
-    }
-
-    @Test
-    public void testDiffList() {
-        // 准备参数
-        Collection<Dog> oldList = Arrays.asList(
-                new Dog(1, "花花", "hh"),
-                new Dog(2, "旺财", "wc")
-        );
-        Collection<Dog> newList = Arrays.asList(
-                new Dog(null, "花花2", "hh"),
-                new Dog(null, "小白", "xb")
-        );
-        BiFunction<Dog, Dog, Boolean> sameFunc = (oldObj, newObj) -> {
-            boolean same = oldObj.getCode().equals(newObj.getCode());
-            // 如果相等的情况下,需要设置下 id,后续好更新
-            if (same) {
-                newObj.setId(oldObj.getId());
-            }
-            return same;
-        };
-
-        // 调用
-        List<List<Dog>> result = CollectionUtils.diffList(oldList, newList, sameFunc);
-        // 断言
-        assertEquals(result.size(), 3);
-        // 断言 create
-        assertEquals(result.get(0).size(), 1);
-        assertEquals(result.get(0).get(0), new Dog(null, "小白", "xb"));
-        // 断言 update
-        assertEquals(result.get(1).size(), 1);
-        assertEquals(result.get(1).get(0), new Dog(1, "花花2", "hh"));
-        // 断言 delete
-        assertEquals(result.get(2).size(), 1);
-        assertEquals(result.get(2).get(0), new Dog(2, "旺财", "wc"));
-    }
-
-}
diff --git a/iailab-framework/pom.xml b/iailab-framework/pom.xml
deleted file mode 100644
index 1ca5b3b..0000000
--- a/iailab-framework/pom.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>iailab-plat</artifactId>
-        <groupId>com.iailab</groupId>
-        <version>${revision}</version>
-    </parent>
-    <packaging>pom</packaging>
-    <modules>
-        <module>iailab-common</module>
-        <module>iailab-common-env</module>
-        <module>iailab-common-mybatis</module>
-        <module>iailab-common-redis</module>
-        <module>iailab-common-web</module>
-        <module>iailab-common-security</module>
-        <module>iailab-common-websocket</module>
-
-        <module>iailab-common-monitor</module>
-        <module>iailab-common-protection</module>
-        <module>iailab-common-job</module>
-        <module>iailab-common-mq</module>
-        <module>iailab-common-rpc</module>
-
-        <module>iailab-common-excel</module>
-        <module>iailab-common-test</module>
-
-        <module>iailab-common-biz-tenant</module>
-        <module>iailab-common-biz-data-permission</module>
-        <module>iailab-common-biz-ip</module>
-    </modules>
-
-    <artifactId>iailab-framework</artifactId>
-    <description>
-        该包是技术组件,每个子包,代表一个组件。每个组件包括两部分:
-            1. core 包:是该组件的核心封装
-            2. config 包:是该组件基于 Spring 的配置
-
-        技术组件,也分成两类:
-            1. 框架组件:和我们熟悉的 MyBatis、Redis 等等的拓展
-            2. 业务组件:和业务相关的组件的封装,例如说数据字典、操作日志等等。
-        如果是业务组件,Maven 名字会包含 biz
-    </description>
-    <url>http://172.16.8.100:8888/summary/iailab-plat.git</url>
-
-    <build>
-        <pluginManagement>
-            <plugins>
-                <!-- maven-surefire-plugin 插件,用于运行单元测试。 -->
-                <!-- 注意,需要使用 3.0.X+,因为要支持 Junit 5 版本 -->
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-surefire-plugin</artifactId>
-                    <version>${maven-surefire-plugin.version}</version>
-                </plugin>
-                <!-- maven-compiler-plugin 插件,解决 Lombok + MapStruct 组合 -->
-                <!-- https://stackoverflow.com/questions/33483697/re-run-spring-boot-configuration-annotation-processor-to-update-generated-metada -->
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-compiler-plugin</artifactId>
-                    <version>${maven-compiler-plugin.version}</version>
-                    <configuration>
-                        <annotationProcessorPaths>
-                            <path>
-                                <groupId>org.springframework.boot</groupId>
-                                <artifactId>spring-boot-configuration-processor</artifactId>
-                                <version>${spring.boot.version}</version>
-                            </path>
-                            <path>
-                                <groupId>org.projectlombok</groupId>
-                                <artifactId>lombok</artifactId>
-                                <version>${lombok.version}</version>
-                            </path>
-                            <path>
-                                <groupId>org.mapstruct</groupId>
-                                <artifactId>mapstruct-processor</artifactId>
-                                <version>${mapstruct.version}</version>
-                            </path>
-                        </annotationProcessorPaths>
-                    </configuration>
-                </plugin>
-            </plugins>
-        </pluginManagement>
-
-        <plugins>
-            <!-- 统一 revision 版本 -->
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>flatten-maven-plugin</artifactId>
-                <version>${flatten-maven-plugin.version}</version>
-                <configuration>
-                    <flattenMode>resolveCiFriendliesOnly</flattenMode>
-                    <updatePomFile>true</updatePomFile>
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>flatten</goal>
-                        </goals>
-                        <id>flatten</id>
-                        <phase>process-resources</phase>
-                    </execution>
-                    <execution>
-                        <goals>
-                            <goal>clean</goal>
-                        </goals>
-                        <id>flatten.clean</id>
-                        <phase>clean</phase>
-                    </execution>
-                </executions>
-            </plugin>
-
-        </plugins>
-    </build>
-
-</project>
diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/SmsCodeApi.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/SmsCodeApi.java
deleted file mode 100644
index a976e7d..0000000
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/SmsCodeApi.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.module.system.api.sms;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
-import com.iailab.module.system.enums.ApiConstants;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-
-import javax.validation.Valid;
-
-@FeignClient(name = ApiConstants.NAME)
-@Tag(name = "RPC 服务 - 短信验证码")
-public interface SmsCodeApi {
-
-    String PREFIX = ApiConstants.PREFIX + "/oauth2/sms/code";
-
-    @PostMapping(PREFIX + "/send")
-    @Operation(summary = "创建短信验证码,并进行发送")
-    CommonResult<Boolean> sendSmsCode(@Valid @RequestBody SmsCodeSendReqDTO reqDTO);
-
-    @PutMapping(PREFIX + "/use")
-    @Operation(summary = "验证短信验证码,并进行使用")
-    CommonResult<Boolean> useSmsCode(@Valid @RequestBody SmsCodeUseReqDTO reqDTO);
-
-    @GetMapping(PREFIX + "/validate")
-    @Operation(summary = "检查验证码是否有效")
-    CommonResult<Boolean> validateSmsCode(@Valid @RequestBody SmsCodeValidateReqDTO reqDTO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/SmsSendApi.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/SmsSendApi.java
deleted file mode 100644
index d1fdca5..0000000
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/SmsSendApi.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.module.system.api.sms;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
-import com.iailab.module.system.enums.ApiConstants;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Operation;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-
-import javax.validation.Valid;
-
-@FeignClient(name = ApiConstants.NAME)
-@Tag(name = "RPC 服务 - 短信发送")
-public interface SmsSendApi {
-
-    String PREFIX = ApiConstants.PREFIX + "/sms/send";
-
-    @PostMapping(PREFIX + "/send-single-admin")
-    @Operation(summary = "发送单条短信给 Admin 用户", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
-    CommonResult<Long> sendSingleSmsToAdmin(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
-
-    @PostMapping(PREFIX + "/send-single-member")
-    @Operation(summary = "发送单条短信给 Member 用户", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
-    CommonResult<Long> sendSingleSmsToMember(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java
deleted file mode 100644
index 425f04e..0000000
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeSendReqDTO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.module.system.api.sms.dto.code;
-
-import com.iailab.framework.common.validation.InEnum;
-import com.iailab.framework.common.validation.Mobile;
-import com.iailab.module.system.enums.sms.SmsSceneEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "RPC 服务 - 短信验证码的发送 Request DTO")
-@Data
-public class SmsCodeSendReqDTO {
-
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @Mobile
-    @NotEmpty(message = "手机号不能为空")
-    private String mobile;
-
-    @Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "发送场景不能为空")
-    @InEnum(SmsSceneEnum.class)
-
-    private Integer scene;
-    @Schema(description = "发送 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.20.30.40")
-    @NotEmpty(message = "发送 IP 不能为空")
-    private String createIp;
-
-}
diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java
deleted file mode 100644
index a9b4d55..0000000
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeUseReqDTO.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.iailab.module.system.api.sms.dto.code;
-
-import com.iailab.framework.common.validation.InEnum;
-import com.iailab.framework.common.validation.Mobile;
-import com.iailab.module.system.enums.sms.SmsSceneEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "RPC 服务 - 短信验证码的使用 Request DTO")
-@Data
-public class SmsCodeUseReqDTO {
-
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @Mobile
-    @NotEmpty(message = "手机号不能为空")
-    private String mobile;
-
-    @Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "发送场景不能为空")
-    @InEnum(SmsSceneEnum.class)
-    private Integer scene;
-
-    @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @NotEmpty(message = "验证码")
-    private String code;
-
-    @Schema(description = "发送 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.20.30.40")
-    @NotEmpty(message = "使用 IP 不能为空")
-    private String usedIp;
-
-}
diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java
deleted file mode 100644
index 11d892f..0000000
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.module.system.api.sms.dto.code;
-
-import com.iailab.framework.common.validation.InEnum;
-import com.iailab.framework.common.validation.Mobile;
-import com.iailab.module.system.enums.sms.SmsSceneEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "RPC 服务 - 短信验证码的校验 Request DTO")
-@Data
-public class SmsCodeValidateReqDTO {
-
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @Mobile
-    @NotEmpty(message = "手机号不能为空")
-    private String mobile;
-
-    @Schema(description = "发送场景", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "发送场景不能为空")
-    @InEnum(SmsSceneEnum.class)
-    private Integer scene;
-
-    @Schema(description = "验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @NotEmpty(message = "验证码")
-    private String code;
-
-}
diff --git a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java b/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java
deleted file mode 100644
index 05f2290..0000000
--- a/iailab-module-system/iailab-module-system-api/src/main/java/com/iailab/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.iailab.module.system.api.sms.dto.send;
-
-import com.iailab.framework.common.validation.Mobile;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotEmpty;
-import java.util.Map;
-
-@Schema(description = "RPC 服务 - 短信发送给 Admin 或者 Member 用户 Request DTO")
-@Data
-public class SmsSendSingleToUserReqDTO {
-
-    @Schema(description = "用户编号", example = "1024")
-    private Long userId;
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @Mobile
-    private String mobile;
-
-    @Schema(description = "短信模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "USER_SEND")
-    @NotEmpty(message = "短信模板编号不能为空")
-    private String templateCode;
-    @Schema(description = "短信模板参数")
-    private Map<String, Object> templateParams;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/pom.xml b/iailab-module-system/iailab-module-system-biz/pom.xml
index 70eed45..c92d927 100644
--- a/iailab-module-system/iailab-module-system-biz/pom.xml
+++ b/iailab-module-system/iailab-module-system-biz/pom.xml
@@ -90,6 +90,12 @@
             <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
         </dependency>
 
+        <!-- Job 定时任务相关 -->
+<!--        <dependency>-->
+<!--            <groupId>com.iailab</groupId>-->
+<!--            <artifactId>iailab-common-job</artifactId>-->
+<!--        </dependency>-->
+
         <!-- 消息队列相关 -->
         <dependency>
             <groupId>com.iailab</groupId>
@@ -126,38 +132,35 @@
             <artifactId>iailab-common-monitor</artifactId>
         </dependency>
 
-        <!-- 三方云服务相关 -->
-        <dependency>
-            <groupId>com.xingyuv</groupId>
-            <artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
-        </dependency>
+<!--        &lt;!&ndash; 三方云服务相关 &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>com.xingyuv</groupId>-->
+<!--            <artifactId>spring-boot-starter-justauth</artifactId> &lt;!&ndash; 社交登陆(例如说,个人微信、企业微信等等) &ndash;&gt;-->
+<!--        </dependency>-->
 
-        <dependency>
-            <groupId>com.github.binarywang</groupId>
-            <artifactId>wx-java-mp-spring-boot-starter</artifactId> <!-- 微信登录(公众号) -->
-        </dependency>
-        <dependency>
-            <groupId>com.github.binarywang</groupId>
-            <artifactId>wx-java-miniapp-spring-boot-starter</artifactId>  <!-- 微信登录(小程序) -->
-        </dependency>
-
-        <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>aliyun-java-sdk-core</artifactId> <!-- 短信(阿里云) -->
-        </dependency>
-        <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <!-- 短信(阿里云) -->
-        </dependency>
-        <dependency>
-            <groupId>com.tencentcloudapi</groupId>
-            <artifactId>tencentcloud-sdk-java-sms</artifactId> <!-- 短信(腾讯云) -->
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.aliyun</groupId>-->
+<!--            <artifactId>aliyun-java-sdk-core</artifactId> &lt;!&ndash; 短信(阿里云) &ndash;&gt;-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>com.aliyun</groupId>-->
+<!--            <artifactId>aliyun-java-sdk-dysmsapi</artifactId> &lt;!&ndash; 短信(阿里云) &ndash;&gt;-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>com.tencentcloudapi</groupId>-->
+<!--            <artifactId>tencentcloud-sdk-java-sms</artifactId> &lt;!&ndash; 短信(腾讯云) &ndash;&gt;-->
+<!--        </dependency>-->
 
         <dependency>
             <groupId>com.xingyuv</groupId>
             <artifactId>spring-boot-starter-captcha-plus</artifactId> <!-- 验证码,一般用于登录使用 -->
         </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>com.iailab</groupId>-->
+<!--            <artifactId>iailab-plat-sdk</artifactId>-->
+<!--            <version>1.0.0</version>-->
+<!--        </dependency>-->
 
     </dependencies>
 
@@ -165,6 +168,45 @@
         <!-- 设置构建的 jar 包名 -->
         <finalName>${project.artifactId}</finalName>
         <plugins>
+            <plugin>
+                <groupId>com.github.wvengen</groupId>
+                <artifactId>proguard-maven-plugin</artifactId>
+                <version>2.7.0</version>
+                <executions>
+                    <!-- 以下配置说明执行mvn的package命令时候,会执行proguard-->
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>proguard</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <!-- 就是输入Jar的名称,我们要知道,代码混淆其实是将一个原始的jar,生成一个混淆后的jar,那么就会有输入输出。 -->
+                    <injar>${project.build.finalName}.jar</injar>
+                    <!-- 输出jar名称,输入输出jar同名的时候就是覆盖,也是比较常用的配置。 -->
+                    <outjar>${project.build.finalName}.jar</outjar>
+                    <!-- 是否混淆 默认是true -->
+                    <obfuscate>true</obfuscate>
+                    <putLibraryJarsInTempDir>true</putLibraryJarsInTempDir>
+                    <!-- 配置一个文件,通常叫做proguard.cfg,该文件主要是配置options选项,也就是说使用proguard.cfg那么options下的所有内容都可以移到proguard.cfg中 -->
+                    <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
+                    <!-- 额外的jar包,通常是项目编译所需要的jar -->
+                    <libs>
+                        <lib>${java.home}/lib/rt.jar</lib>
+                        <lib>${java.home}/lib/jce.jar</lib>
+                        <lib>${java.home}/lib/jsse.jar</lib>
+                    </libs>
+                    <!-- 对输入jar进行过滤比如,如下配置就是对META-INFO文件不处理。 -->
+                    <inLibsFilter>!META-INF/**,!META-INF/versions/9/**.class</inLibsFilter>
+                    <!-- 这是输出路径配置,但是要注意这个路径必须要包括injar标签填写的jar -->
+                    <outputDirectory>${project.basedir}/target</outputDirectory>
+                    <!--这里特别重要,此处主要是配置混淆的一些细节选项,比如哪些类不需要混淆,哪些需要混淆-->
+                    <options>
+                        <!-- 可以在此处写option标签配置,不过我上面使用了proguardInclude,故而我更喜欢在proguard.cfg中配置 -->
+                    </options>
+                </configuration>
+            </plugin>
             <!-- 打包 -->
             <plugin>
                 <groupId>org.springframework.boot</groupId>
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/sms/SmsCodeApiImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/sms/SmsCodeApiImpl.java
deleted file mode 100644
index 4f31dda..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/sms/SmsCodeApiImpl.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.module.system.api.sms;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
-import com.iailab.module.system.service.sms.SmsCodeService;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@RestController // 提供 RESTful API 接口,给 Feign 调用
-@Validated
-public class SmsCodeApiImpl implements SmsCodeApi {
-
-    @Resource
-    private SmsCodeService smsCodeService;
-
-    @Override
-    public CommonResult<Boolean> sendSmsCode(SmsCodeSendReqDTO reqDTO) {
-        smsCodeService.sendSmsCode(reqDTO);
-        return success(true);
-    }
-
-    @Override
-    public CommonResult<Boolean> useSmsCode(SmsCodeUseReqDTO reqDTO) {
-        smsCodeService.useSmsCode(reqDTO);
-        return success(true);
-    }
-
-    @Override
-    public CommonResult<Boolean> validateSmsCode(SmsCodeValidateReqDTO reqDTO) {
-        smsCodeService.validateSmsCode(reqDTO);
-        return success(true);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/sms/SmsSendApiImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/sms/SmsSendApiImpl.java
deleted file mode 100644
index f68c108..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/sms/SmsSendApiImpl.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.iailab.module.system.api.sms;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
-import com.iailab.module.system.service.sms.SmsSendService;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@RestController // 提供 RESTful API 接口,给 Feign 调用
-@Validated
-public class SmsSendApiImpl implements SmsSendApi {
-
-    @Resource
-    private SmsSendService smsSendService;
-
-    @Override
-    public CommonResult<Long> sendSingleSmsToAdmin(SmsSendSingleToUserReqDTO reqDTO) {
-        return success(smsSendService.sendSingleSmsToAdmin(reqDTO.getMobile(), reqDTO.getUserId(),
-                reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
-    }
-
-    @Override
-    public CommonResult<Long> sendSingleSmsToMember(SmsSendSingleToUserReqDTO reqDTO) {
-        return success(smsSendService.sendSingleSmsToMember(reqDTO.getMobile(), reqDTO.getUserId(),
-                reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/social/SocialClientApiImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/social/SocialClientApiImpl.java
deleted file mode 100644
index 265adc6..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/social/SocialClientApiImpl.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.module.system.api.social;
-
-import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO;
-import com.iailab.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
-import com.iailab.module.system.service.social.SocialClientService;
-import me.chanjar.weixin.common.bean.WxJsapiSignature;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-/**
- * 社交应用的 API 实现类
- *
- * @author iailab
- */
-@RestController
-@Validated
-public class SocialClientApiImpl implements SocialClientApi {
-
-    @Resource
-    private SocialClientService socialClientService;
-
-    @Override
-    public CommonResult<String> getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) {
-        return success(socialClientService.getAuthorizeUrl(socialType, userType, redirectUri));
-    }
-
-    @Override
-    public CommonResult<SocialWxJsapiSignatureRespDTO> createWxMpJsapiSignature(Integer userType, String url) {
-        WxJsapiSignature signature = socialClientService.createWxMpJsapiSignature(userType, url);
-        return success(BeanUtils.toBean(signature, SocialWxJsapiSignatureRespDTO.class));
-    }
-
-    @Override
-    public CommonResult<SocialWxPhoneNumberInfoRespDTO> getWxMaPhoneNumberInfo(Integer userType, String phoneCode) {
-        WxMaPhoneNumberInfo info = socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode);
-        return success(BeanUtils.toBean(info, SocialWxPhoneNumberInfoRespDTO.class));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/social/SocialUserApiImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/social/SocialUserApiImpl.java
deleted file mode 100644
index c8d03f6..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/api/social/SocialUserApiImpl.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.iailab.module.system.api.social;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
-import com.iailab.module.system.api.social.dto.SocialUserUnbindReqDTO;
-import com.iailab.module.system.service.social.SocialUserService;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@RestController // 提供 RESTful API 接口,给 Feign 调用
-@Validated
-public class SocialUserApiImpl implements SocialUserApi {
-
-    @Resource
-    private SocialUserService socialUserService;
-
-    @Override
-    public CommonResult<String> bindSocialUser(SocialUserBindReqDTO reqDTO) {
-        return success(socialUserService.bindSocialUser(reqDTO));
-    }
-
-    @Override
-    public CommonResult<Boolean> unbindSocialUser(SocialUserUnbindReqDTO reqDTO) {
-        socialUserService.unbindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(),
-                reqDTO.getSocialType(), reqDTO.getOpenid());
-        return success(true);
-    }
-
-    @Override
-    public CommonResult<SocialUserRespDTO> getSocialUserByUserId(Integer userType, Long userId, Integer socialType) {
-        return success(socialUserService.getSocialUserByUserId(userType, userId, socialType));
-    }
-
-    @Override
-    public CommonResult<SocialUserRespDTO> getSocialUserByCode(Integer userType, Integer socialType, String code, String state) {
-        return success(socialUserService.getSocialUserByCode(userType, socialType, code, state));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
index 2fcd758..c3c0e3c 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/auth/AuthController.java
@@ -4,17 +4,12 @@
 import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.util.StrUtil;
 import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
 import com.iailab.framework.common.pojo.CommonResult;
 import com.iailab.framework.common.util.object.BeanUtils;
 import com.iailab.framework.security.config.SecurityProperties;
-import com.iailab.framework.security.core.LoginUser;
 import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
-import com.iailab.module.system.controller.admin.app.vo.AppMenuRespVO;
 import com.iailab.module.system.controller.admin.app.vo.AppRespVO;
 import com.iailab.module.system.controller.admin.auth.vo.*;
-import com.iailab.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
-import com.iailab.module.system.controller.admin.permission.vo.menu.MenuRespVO;
 import com.iailab.module.system.convert.auth.AuthConvert;
 import com.iailab.module.system.dal.dataobject.app.AppDO;
 import com.iailab.module.system.dal.dataobject.permission.MenuDO;
@@ -27,14 +22,11 @@
 import com.iailab.module.system.service.permission.MenuService;
 import com.iailab.module.system.service.permission.PermissionService;
 import com.iailab.module.system.service.permission.RoleService;
-import com.iailab.module.system.service.social.SocialClientService;
 import com.iailab.module.system.service.user.AdminUserService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.security.core.Authentication;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -68,8 +60,6 @@
     private MenuService menuService;
     @Resource
     private PermissionService permissionService;
-    @Resource
-    private SocialClientService socialClientService;
     @Resource
     private SecurityProperties securityProperties;
     @Resource
@@ -264,45 +254,6 @@
         menuVOS = AuthConvert.INSTANCE.buildMenuTree(tempChildren, menuDO.getId(), menuDO.getPath(), info.getType());
         // 2. 拼接结果返回
         return success(menuVOS);
-    }
-
-    // ========== 短信登录相关 ==========
-
-    @PostMapping("/sms-login")
-    @PermitAll
-    @Operation(summary = "使用短信验证码登录")
-    public CommonResult<AuthLoginRespVO> smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) {
-        return success(authService.smsLogin(reqVO));
-    }
-
-    @PostMapping("/send-sms-code")
-    @PermitAll
-    @Operation(summary = "发送手机验证码")
-    public CommonResult<Boolean> sendLoginSmsCode(@RequestBody @Valid AuthSmsSendReqVO reqVO) {
-        authService.sendSmsCode(reqVO);
-        return success(true);
-    }
-
-    // ========== 社交登录相关 ==========
-
-    @GetMapping("/social-auth-redirect")
-    @PermitAll
-    @Operation(summary = "社交授权的跳转")
-    @Parameters({
-            @Parameter(name = "type", description = "社交类型", required = true),
-            @Parameter(name = "redirectUri", description = "回调路径")
-    })
-    public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
-                                            @RequestParam("redirectUri") String redirectUri) {
-        return success(socialClientService.getAuthorizeUrl(
-                type, UserTypeEnum.ADMIN.getValue(), redirectUri));
-    }
-
-    @PostMapping("/social-login")
-    @PermitAll
-    @Operation(summary = "社交快捷登录,使用 code 授权码", description = "适合未登录的用户,但是社交账号已绑定用户")
-    public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialLoginReqVO reqVO) {
-        return success(authService.socialLogin(reqVO));
     }
 
 }
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsCallbackController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsCallbackController.java
deleted file mode 100644
index 8eb8495..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsCallbackController.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.iailab.module.system.controller.admin.sms;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.util.servlet.ServletUtils;
-import com.iailab.module.system.framework.sms.core.enums.SmsChannelEnum;
-import com.iailab.module.system.service.sms.SmsSendService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-import javax.annotation.security.PermitAll;
-import javax.servlet.http.HttpServletRequest;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "管理后台 - 短信回调")
-@RestController
-@RequestMapping("/system/sms/callback")
-public class SmsCallbackController {
-
-    @Resource
-    private SmsSendService smsSendService;
-
-    @PostMapping("/aliyun")
-    @PermitAll
-    @Operation(summary = "阿里云短信的回调", description = "参见 https://help.aliyun.com/zh/sms/developer-reference/configure-delivery-receipts-1 文档")
-    public CommonResult<Boolean> receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable {
-        String text = ServletUtils.getBody(request);
-        smsSendService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text);
-        return success(true);
-    }
-
-    @PostMapping("/tencent")
-    @PermitAll
-    @Operation(summary = "腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/59178 文档")
-    public CommonResult<Boolean> receiveTencentSmsStatus(HttpServletRequest request) throws Throwable {
-        String text = ServletUtils.getBody(request);
-        smsSendService.receiveSmsStatus(SmsChannelEnum.TENCENT.getCode(), text);
-        return success(true);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsChannelController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsChannelController.java
deleted file mode 100644
index 577245e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsChannelController.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.iailab.module.system.controller.admin.sms;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelRespVO;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelSimpleRespVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.service.sms.SmsChannelService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.validation.Valid;
-import java.util.Comparator;
-import java.util.List;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "管理后台 - 短信渠道")
-@RestController
-@RequestMapping("system/sms-channel")
-public class SmsChannelController {
-
-    @Resource
-    private SmsChannelService smsChannelService;
-
-    @PostMapping("/create")
-    @Operation(summary = "创建短信渠道")
-    @PreAuthorize("@ss.hasPermission('system:sms-channel:create')")
-    public CommonResult<Long> createSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO createReqVO) {
-        return success(smsChannelService.createSmsChannel(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "更新短信渠道")
-    @PreAuthorize("@ss.hasPermission('system:sms-channel:update')")
-    public CommonResult<Boolean> updateSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO updateReqVO) {
-        smsChannelService.updateSmsChannel(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "删除短信渠道")
-    @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('system:sms-channel:delete')")
-    public CommonResult<Boolean> deleteSmsChannel(@RequestParam("id") Long id) {
-        smsChannelService.deleteSmsChannel(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "获得短信渠道")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
-    public CommonResult<SmsChannelRespVO> getSmsChannel(@RequestParam("id") Long id) {
-        SmsChannelDO channel = smsChannelService.getSmsChannel(id);
-        return success(BeanUtils.toBean(channel, SmsChannelRespVO.class));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "获得短信渠道分页")
-    @PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
-    public CommonResult<PageResult<SmsChannelRespVO>> getSmsChannelPage(@Valid SmsChannelPageReqVO pageVO) {
-        PageResult<SmsChannelDO> pageResult = smsChannelService.getSmsChannelPage(pageVO);
-        return success(BeanUtils.toBean(pageResult, SmsChannelRespVO.class));
-    }
-
-    @GetMapping({"/list-all-simple", "/simple-list"})
-    @Operation(summary = "获得短信渠道精简列表", description = "包含被禁用的短信渠道")
-    public CommonResult<List<SmsChannelSimpleRespVO>> getSimpleSmsChannelList() {
-        List<SmsChannelDO> list = smsChannelService.getSmsChannelList();
-        list.sort(Comparator.comparing(SmsChannelDO::getId));
-        return success(BeanUtils.toBean(list, SmsChannelSimpleRespVO.class));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsLogController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsLogController.java
deleted file mode 100644
index 0fd6893..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsLogController.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.iailab.module.system.controller.admin.sms;
-
-import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.pojo.PageParam;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.framework.excel.core.util.ExcelUtils;
-import com.iailab.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.log.SmsLogRespVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsLogDO;
-import com.iailab.module.system.service.sms.SmsLogService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.List;
-
-import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "管理后台 - 短信日志")
-@RestController
-@RequestMapping("/system/sms-log")
-@Validated
-public class SmsLogController {
-
-    @Resource
-    private SmsLogService smsLogService;
-
-    @GetMapping("/page")
-    @Operation(summary = "获得短信日志分页")
-    @PreAuthorize("@ss.hasPermission('system:sms-log:query')")
-    public CommonResult<PageResult<SmsLogRespVO>> getSmsLogPage(@Valid SmsLogPageReqVO pageReqVO) {
-        PageResult<SmsLogDO> pageResult = smsLogService.getSmsLogPage(pageReqVO);
-        return success(BeanUtils.toBean(pageResult, SmsLogRespVO.class));
-    }
-
-    @GetMapping("/export-excel")
-    @Operation(summary = "导出短信日志 Excel")
-    @PreAuthorize("@ss.hasPermission('system:sms-log:export')")
-    @ApiAccessLog(operateType = EXPORT)
-    public void exportSmsLogExcel(@Valid SmsLogPageReqVO exportReqVO,
-                                  HttpServletResponse response) throws IOException {
-        exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<SmsLogDO> list = smsLogService.getSmsLogPage(exportReqVO).getList();
-        // 导出 Excel
-        ExcelUtils.write(response, "短信日志.xls", "数据", SmsLogRespVO.class,
-                BeanUtils.toBean(list, SmsLogRespVO.class));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsTemplateController.http b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsTemplateController.http
deleted file mode 100644
index ee24e92..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsTemplateController.http
+++ /dev/null
@@ -1,14 +0,0 @@
-### 请求 /system/sms-template/send-sms 接口 => 成功
-POST {{baseUrl}}/system/sms-template/send-sms
-Authorization: Bearer {{token}}
-Content-Type: application/json
-tenant-id: {{adminTenentId}}
-
-{
-  "templateCode": "test_01",
-  "mobile": "15601691390",
-  "templateParams": {
-    "operation": "value01",
-    "code": "value02"
-  }
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsTemplateController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsTemplateController.java
deleted file mode 100644
index 752d15a..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/SmsTemplateController.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.iailab.module.system.controller.admin.sms;
-
-import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.pojo.PageParam;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.framework.excel.core.util.ExcelUtils;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.service.sms.SmsSendService;
-import com.iailab.module.system.service.sms.SmsTemplateService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.List;
-
-import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "管理后台 - 短信模板")
-@RestController
-@RequestMapping("/system/sms-template")
-public class SmsTemplateController {
-
-    @Resource
-    private SmsTemplateService smsTemplateService;
-    @Resource
-    private SmsSendService smsSendService;
-
-    @PostMapping("/create")
-    @Operation(summary = "创建短信模板")
-    @PreAuthorize("@ss.hasPermission('system:sms-template:create')")
-    public CommonResult<Long> createSmsTemplate(@Valid @RequestBody SmsTemplateSaveReqVO createReqVO) {
-        return success(smsTemplateService.createSmsTemplate(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "更新短信模板")
-    @PreAuthorize("@ss.hasPermission('system:sms-template:update')")
-    public CommonResult<Boolean> updateSmsTemplate(@Valid @RequestBody SmsTemplateSaveReqVO updateReqVO) {
-        smsTemplateService.updateSmsTemplate(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "删除短信模板")
-    @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('system:sms-template:delete')")
-    public CommonResult<Boolean> deleteSmsTemplate(@RequestParam("id") Long id) {
-        smsTemplateService.deleteSmsTemplate(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "获得短信模板")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('system:sms-template:query')")
-    public CommonResult<SmsTemplateRespVO> getSmsTemplate(@RequestParam("id") Long id) {
-        SmsTemplateDO template = smsTemplateService.getSmsTemplate(id);
-        return success(BeanUtils.toBean(template, SmsTemplateRespVO.class));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "获得短信模板分页")
-    @PreAuthorize("@ss.hasPermission('system:sms-template:query')")
-    public CommonResult<PageResult<SmsTemplateRespVO>> getSmsTemplatePage(@Valid SmsTemplatePageReqVO pageVO) {
-        PageResult<SmsTemplateDO> pageResult = smsTemplateService.getSmsTemplatePage(pageVO);
-        return success(BeanUtils.toBean(pageResult, SmsTemplateRespVO.class));
-    }
-
-    @GetMapping("/export-excel")
-    @Operation(summary = "导出短信模板 Excel")
-    @PreAuthorize("@ss.hasPermission('system:sms-template:export')")
-    @ApiAccessLog(operateType = EXPORT)
-    public void exportSmsTemplateExcel(@Valid SmsTemplatePageReqVO exportReqVO,
-                                       HttpServletResponse response) throws IOException {
-        exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<SmsTemplateDO> list = smsTemplateService.getSmsTemplatePage(exportReqVO).getList();
-        // 导出 Excel
-        ExcelUtils.write(response, "短信模板.xls", "数据", SmsTemplateRespVO.class,
-                BeanUtils.toBean(list, SmsTemplateRespVO.class));
-    }
-
-    @PostMapping("/send-sms")
-    @Operation(summary = "发送短信")
-    @PreAuthorize("@ss.hasPermission('system:sms-template:send-sms')")
-    public CommonResult<Long> sendSms(@Valid @RequestBody SmsTemplateSendReqVO sendReqVO) {
-        return success(smsSendService.sendSingleSmsToAdmin(sendReqVO.getMobile(), null,
-                sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java
deleted file mode 100644
index f719478..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelPageReqVO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.channel;
-
-import com.iailab.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - 短信渠道分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SmsChannelPageReqVO extends PageParam {
-
-    @Schema(description = "任务状态", example = "1")
-    private Integer status;
-
-    @Schema(description = "短信签名,模糊匹配", example = "iailab")
-    private String signature;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "创建时间")
-    private LocalDateTime[] createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java
deleted file mode 100644
index 6f6d006..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.channel;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.hibernate.validator.constraints.URL;
-
-import javax.validation.constraints.NotNull;
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - 短信渠道 Response VO")
-@Data
-public class SmsChannelRespVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long id;
-
-    @Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    @NotNull(message = "短信签名不能为空")
-    private String signature;
-
-    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
-    private String code;
-
-    @Schema(description = "启用状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "启用状态不能为空")
-    private Integer status;
-
-    @Schema(description = "备注", example = "好吃!")
-    private String remark;
-
-    @Schema(description = "短信 API 的账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    @NotNull(message = "短信 API 的账号不能为空")
-    private String apiKey;
-
-    @Schema(description = "短信 API 的密钥", example = "yuanma")
-    private String apiSecret;
-
-    @Schema(description = "短信发送回调 URL", example = "https://www.baidu.com")
-    @URL(message = "回调 URL 格式不正确")
-    private String callbackUrl;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelSaveReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelSaveReqVO.java
deleted file mode 100644
index ae78ff2..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelSaveReqVO.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.channel;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.hibernate.validator.constraints.URL;
-
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - 短信渠道创建/修改 Request VO")
-@Data
-public class SmsChannelSaveReqVO {
-
-    @Schema(description = "编号", example = "1024")
-    private Long id;
-
-    @Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    @NotNull(message = "短信签名不能为空")
-    private String signature;
-
-    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
-    @NotNull(message = "渠道编码不能为空")
-    private String code;
-
-    @Schema(description = "启用状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "启用状态不能为空")
-    private Integer status;
-
-    @Schema(description = "备注", example = "好吃!")
-    private String remark;
-
-    @Schema(description = "短信 API 的账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    @NotNull(message = "短信 API 的账号不能为空")
-    private String apiKey;
-
-    @Schema(description = "短信 API 的密钥", example = "yuanma")
-    private String apiSecret;
-
-    @Schema(description = "短信发送回调 URL", example = "")
-    @URL(message = "回调 URL 格式不正确")
-    private String callbackUrl;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java
deleted file mode 100644
index 1b441c8..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.channel;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-@Schema(description = "管理后台 - 短信渠道精简 Response VO")
-@Data
-public class SmsChannelSimpleRespVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    private Long id;
-
-    @Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    private String signature;
-
-    @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN")
-    private String code;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java
deleted file mode 100644
index 86360ba..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/log/SmsLogPageReqVO.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.log;
-
-import com.iailab.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - 短信日志分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SmsLogPageReqVO extends PageParam {
-
-    @Schema(description = "短信渠道编号", example = "10")
-    private Long channelId;
-
-    @Schema(description = "模板编号", example = "20")
-    private Long templateId;
-
-    @Schema(description = "手机号", example = "15601691300")
-    private String mobile;
-
-    @Schema(description = "发送状态,参见 SmsSendStatusEnum 枚举类", example = "1")
-    private Integer sendStatus;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "发送时间")
-    private LocalDateTime[] sendTime;
-
-    @Schema(description = "接收状态,参见 SmsReceiveStatusEnum 枚举类", example = "0")
-    private Integer receiveStatus;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "接收时间")
-    private LocalDateTime[] receiveTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java
deleted file mode 100644
index 99e5570..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.log;
-
-import com.iailab.framework.excel.core.annotations.DictFormat;
-import com.iailab.framework.excel.core.convert.DictConvert;
-import com.iailab.framework.excel.core.convert.JsonConvert;
-import com.iailab.module.system.enums.DictTypeConstants;
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-import java.util.Map;
-
-@Schema(description = "管理后台 - 短信日志 Response VO")
-@Data
-@ExcelIgnoreUnannotated
-public class SmsLogRespVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @ExcelProperty("编号")
-    private Long id;
-
-    @Schema(description = "短信渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @ExcelProperty("短信渠道编号")
-    private Long channelId;
-
-    @Schema(description = "短信渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ALIYUN")
-    @ExcelProperty("短信渠道编码")
-    private String channelCode;
-
-    @Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
-    @ExcelProperty("模板编号")
-    private Long templateId;
-
-    @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test-01")
-    @ExcelProperty("模板编码")
-    private String templateCode;
-
-    @Schema(description = "短信类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @ExcelProperty(value = "短信类型", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE)
-    private Integer templateType;
-
-    @Schema(description = "短信内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你的验证码是 1024")
-    @ExcelProperty("短信内容")
-    private String templateContent;
-
-    @Schema(description = "短信参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "name,code")
-    @ExcelProperty(value = "短信参数", converter = JsonConvert.class)
-    private Map<String, Object> templateParams;
-
-    @Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SMS_207945135")
-    @ExcelProperty("短信 API 的模板编号")
-    private String apiTemplateId;
-
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @ExcelProperty("手机号")
-    private String mobile;
-
-    @Schema(description = "用户编号", example = "10")
-    @ExcelProperty("用户编号")
-    private Long userId;
-
-    @Schema(description = "用户类型", example = "1")
-    @ExcelProperty(value = "用户类型", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.USER_TYPE)
-    private Integer userType;
-
-    @Schema(description = "发送状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @ExcelProperty(value = "发送状态", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.SMS_SEND_STATUS)
-    private Integer sendStatus;
-
-    @Schema(description = "发送时间")
-    @ExcelProperty("发送时间")
-    private LocalDateTime sendTime;
-
-    @Schema(description = "短信 API 发送结果的编码", example = "SUCCESS")
-    @ExcelProperty("短信 API 发送结果的编码")
-    private String apiSendCode;
-
-    @Schema(description = "短信 API 发送失败的提示", example = "成功")
-    @ExcelProperty("短信 API 发送失败的提示")
-    private String apiSendMsg;
-
-    @Schema(description = "短信 API 发送返回的唯一请求 ID", example = "3837C6D3-B96F-428C-BBB2-86135D4B5B99")
-    @ExcelProperty("短信 API 发送返回的唯一请求 ID")
-    private String apiRequestId;
-
-    @Schema(description = "短信 API 发送返回的序号", example = "62923244790")
-    @ExcelProperty("短信 API 发送返回的序号")
-    private String apiSerialNo;
-
-    @Schema(description = "接收状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    @ExcelProperty(value = "接收状态", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.SMS_RECEIVE_STATUS)
-    private Integer receiveStatus;
-
-    @Schema(description = "接收时间")
-    @ExcelProperty("接收时间")
-    private LocalDateTime receiveTime;
-
-    @Schema(description = "API 接收结果的编码", example = "DELIVRD")
-    @ExcelProperty("API 接收结果的编码")
-    private String apiReceiveCode;
-
-    @Schema(description = "API 接收结果的说明", example = "用户接收成功")
-    @ExcelProperty("API 接收结果的说明")
-    private String apiReceiveMsg;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("创建时间")
-    private LocalDateTime createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java
deleted file mode 100644
index 364f5ff..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.template;
-
-import com.iailab.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - 短信模板分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SmsTemplatePageReqVO extends PageParam {
-
-    @Schema(description = "短信签名", example = "1")
-    private Integer type;
-
-    @Schema(description = "开启状态", example = "1")
-    private Integer status;
-
-    @Schema(description = "模板编码,模糊匹配", example = "test_01")
-    private String code;
-
-    @Schema(description = "模板内容,模糊匹配", example = "你好,{name}。你长的太{like}啦!")
-    private String content;
-
-    @Schema(description = "短信 API 的模板编号,模糊匹配", example = "4383920")
-    private String apiTemplateId;
-
-    @Schema(description = "短信渠道编号", example = "10")
-    private Long channelId;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @Schema(description = "创建时间")
-    private LocalDateTime[] createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java
deleted file mode 100644
index deb9e40..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.template;
-
-import com.iailab.framework.excel.core.annotations.DictFormat;
-import com.iailab.framework.excel.core.convert.DictConvert;
-import com.iailab.module.system.enums.DictTypeConstants;
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Schema(description = "管理后台 - 短信模板 Response VO")
-@Data
-@ExcelIgnoreUnannotated
-public class SmsTemplateRespVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @ExcelProperty("编号")
-    private Long id;
-
-    @Schema(description = "短信类型,参见 SmsTemplateTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @ExcelProperty(value = "短信签名", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE)
-    private Integer type;
-
-    @Schema(description = "开启状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @ExcelProperty(value = "开启状态", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.COMMON_STATUS)
-    private Integer status;
-
-    @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
-    @ExcelProperty("模板编码")
-    private String code;
-
-    @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    @ExcelProperty("模板名称")
-    private String name;
-
-    @Schema(description = "模板内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,{name}。你长的太{like}啦!")
-    @ExcelProperty("模板内容")
-    private String content;
-
-    @Schema(description = "参数数组", example = "name,code")
-    private List<String> params;
-
-    @Schema(description = "备注", example = "哈哈哈")
-    @ExcelProperty("备注")
-    private String remark;
-
-    @Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4383920")
-    @ExcelProperty("短信 API 的模板编号")
-    private String apiTemplateId;
-
-    @Schema(description = "短信渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @ExcelProperty("短信渠道编号")
-    private Long channelId;
-
-    @Schema(description = "短信渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ALIYUN")
-    @ExcelProperty(value = "短信渠道编码", converter = DictConvert.class)
-    @DictFormat(DictTypeConstants.SMS_CHANNEL_CODE)
-    private String channelCode;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("创建时间")
-    private LocalDateTime createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java
deleted file mode 100644
index 52a8695..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.template;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - 短信模板创建/修改 Request VO")
-@Data
-public class SmsTemplateSaveReqVO {
-
-    @Schema(description = "编号", example = "1024")
-    private Long id;
-
-    @Schema(description = "短信类型,参见 SmsTemplateTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "短信类型不能为空")
-    private Integer type;
-
-    @Schema(description = "开启状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "开启状态不能为空")
-    private Integer status;
-
-    @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
-    @NotNull(message = "模板编码不能为空")
-    private String code;
-
-    @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    @NotNull(message = "模板名称不能为空")
-    private String name;
-
-    @Schema(description = "模板内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,{name}。你长的太{like}啦!")
-    @NotNull(message = "模板内容不能为空")
-    private String content;
-
-    @Schema(description = "备注", example = "哈哈哈")
-    private String remark;
-
-    @Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4383920")
-    @NotNull(message = "短信 API 的模板编号不能为空")
-    private String apiTemplateId;
-
-    @Schema(description = "短信渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @NotNull(message = "短信渠道编号不能为空")
-    private Long channelId;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateSendReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateSendReqVO.java
deleted file mode 100644
index 3631878..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/sms/vo/template/SmsTemplateSendReqVO.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.iailab.module.system.controller.admin.sms.vo.template;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-import java.util.Map;
-
-@Schema(description = "管理后台 - 短信模板的发送 Request VO")
-@Data
-public class SmsTemplateSendReqVO {
-
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @NotNull(message = "手机号不能为空")
-    private String mobile;
-
-    @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
-    @NotNull(message = "模板编码不能为空")
-    private String templateCode;
-
-    @Schema(description = "模板参数")
-    private Map<String, Object> templateParams;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/SocialClientController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/SocialClientController.java
deleted file mode 100644
index 685119e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/SocialClientController.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.iailab.module.system.controller.admin.socail;
-
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientRespVO;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialClientDO;
-import com.iailab.module.system.service.social.SocialClientService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.validation.Valid;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-
-@Tag(name = "管理后台 - 社交客户端")
-@RestController
-@RequestMapping("/system/social-client")
-@Validated
-public class SocialClientController {
-
-    @Resource
-    private SocialClientService socialClientService;
-
-    @PostMapping("/create")
-    @Operation(summary = "创建社交客户端")
-    @PreAuthorize("@ss.hasPermission('system:social-client:create')")
-    public CommonResult<Long> createSocialClient(@Valid @RequestBody SocialClientSaveReqVO createReqVO) {
-        return success(socialClientService.createSocialClient(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @Operation(summary = "更新社交客户端")
-    @PreAuthorize("@ss.hasPermission('system:social-client:update')")
-    public CommonResult<Boolean> updateSocialClient(@Valid @RequestBody SocialClientSaveReqVO updateReqVO) {
-        socialClientService.updateSocialClient(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @Operation(summary = "删除社交客户端")
-    @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('system:social-client:delete')")
-    public CommonResult<Boolean> deleteSocialClient(@RequestParam("id") Long id) {
-        socialClientService.deleteSocialClient(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @Operation(summary = "获得社交客户端")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('system:social-client:query')")
-    public CommonResult<SocialClientRespVO> getSocialClient(@RequestParam("id") Long id) {
-        SocialClientDO client = socialClientService.getSocialClient(id);
-        return success(BeanUtils.toBean(client, SocialClientRespVO.class));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "获得社交客户端分页")
-    @PreAuthorize("@ss.hasPermission('system:social-client:query')")
-    public CommonResult<PageResult<SocialClientRespVO>> getSocialClientPage(@Valid SocialClientPageReqVO pageVO) {
-        PageResult<SocialClientDO> pageResult = socialClientService.getSocialClientPage(pageVO);
-        return success(BeanUtils.toBean(pageResult, SocialClientRespVO.class));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/SocialUserController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/SocialUserController.java
deleted file mode 100644
index 78cd6ee..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/SocialUserController.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.iailab.module.system.controller.admin.socail;
-
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.pojo.CommonResult;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserUnbindReqVO;
-import com.iailab.module.system.convert.social.SocialUserConvert;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
-import com.iailab.module.system.service.social.SocialUserService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.validation.Valid;
-
-import static com.iailab.framework.common.pojo.CommonResult.success;
-import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
-
-@Tag(name = "管理后台 - 社交用户")
-@RestController
-@RequestMapping("/system/social-user")
-@Validated
-public class SocialUserController {
-
-    @Resource
-    private SocialUserService socialUserService;
-
-    @PostMapping("/bind")
-    @Operation(summary = "社交绑定,使用 code 授权码")
-    public CommonResult<Boolean> socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) {
-        socialUserService.bindSocialUser(SocialUserConvert.INSTANCE.convert(
-                getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO));
-        return CommonResult.success(true);
-    }
-
-    @DeleteMapping("/unbind")
-    @Operation(summary = "取消社交绑定")
-    public CommonResult<Boolean> socialUnbind(@RequestBody SocialUserUnbindReqVO reqVO) {
-        socialUserService.unbindSocialUser(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getOpenid());
-        return CommonResult.success(true);
-    }
-
-    // ==================== 社交用户 CRUD ====================
-
-    @GetMapping("/get")
-    @Operation(summary = "获得社交用户")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('system:social-user:query')")
-    public CommonResult<SocialUserRespVO> getSocialUser(@RequestParam("id") Long id) {
-        SocialUserDO socialUser = socialUserService.getSocialUser(id);
-        return success(BeanUtils.toBean(socialUser, SocialUserRespVO.class));
-    }
-
-    @GetMapping("/page")
-    @Operation(summary = "获得社交用户分页")
-    @PreAuthorize("@ss.hasPermission('system:social-user:query')")
-    public CommonResult<PageResult<SocialUserRespVO>> getSocialUserPage(@Valid SocialUserPageReqVO pageVO) {
-        PageResult<SocialUserDO> pageResult = socialUserService.getSocialUserPage(pageVO);
-        return success(BeanUtils.toBean(pageResult, SocialUserRespVO.class));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientPageReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientPageReqVO.java
deleted file mode 100644
index 6f41fe1..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientPageReqVO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.client;
-
-import com.iailab.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "管理后台 - 社交客户端分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SocialClientPageReqVO extends PageParam {
-
-    @Schema(description = "应用名", example = "iailab商城")
-    private String name;
-
-    @Schema(description = "社交平台的类型", example = "31")
-    private Integer socialType;
-
-    @Schema(description = "用户类型", example = "2")
-    private Integer userType;
-
-    @Schema(description = "客户端编号", example = "145442115")
-    private String clientId;
-
-    @Schema(description = "状态", example = "1")
-    private Integer status;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java
deleted file mode 100644
index 470bd35..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.client;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - 社交客户端 Response VO")
-@Data
-public class SocialClientRespVO {
-
-    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27162")
-    private Long id;
-
-    @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab商城")
-    private String name;
-
-    @Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "31")
-    private Integer socialType;
-
-    @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
-    private Integer userType;
-
-    @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "wwd411c69a39ad2e54")
-    private String clientId;
-
-    @Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "peter")
-    private String clientSecret;
-
-    @Schema(description = "授权方的网页应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000045")
-    private String agentId;
-
-    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer status;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientSaveReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientSaveReqVO.java
deleted file mode 100644
index 8866c64..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/client/SocialClientSaveReqVO.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.client;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.common.validation.InEnum;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import javax.validation.constraints.AssertTrue;
-import javax.validation.constraints.NotNull;
-import java.util.Objects;
-
-@Schema(description = "管理后台 - 社交客户端创建/修改 Request VO")
-@Data
-public class SocialClientSaveReqVO {
-
-    @Schema(description = "编号", example = "27162")
-    private Long id;
-
-    @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab商城")
-    @NotNull(message = "应用名不能为空")
-    private String name;
-
-    @Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "31")
-    @NotNull(message = "社交平台的类型不能为空")
-    @InEnum(SocialTypeEnum.class)
-    private Integer socialType;
-
-    @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
-    @NotNull(message = "用户类型不能为空")
-    @InEnum(UserTypeEnum.class)
-    private Integer userType;
-
-    @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "wwd411c69a39ad2e54")
-    @NotNull(message = "客户端编号不能为空")
-    private String clientId;
-
-    @Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "peter")
-    @NotNull(message = "客户端密钥不能为空")
-    private String clientSecret;
-
-    @Schema(description = "授权方的网页应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000045")
-    private String agentId;
-
-    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "状态不能为空")
-    @InEnum(CommonStatusEnum.class)
-    private Integer status;
-
-    @AssertTrue(message = "agentId 不能为空")
-    @JsonIgnore
-    public boolean isAgentIdValid() {
-        // 如果是企业微信,必须填写 agentId 属性
-        return !Objects.equals(socialType, SocialTypeEnum.WECHAT_ENTERPRISE.getType())
-                || !StrUtil.isEmpty(agentId);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java
deleted file mode 100644
index ca9f9af..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.user;
-
-import com.iailab.framework.common.validation.InEnum;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - 社交绑定 Request VO,使用 code 授权码")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class SocialUserBindReqVO {
-
-    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @InEnum(SocialTypeEnum.class)
-    @NotNull(message = "社交平台的类型不能为空")
-    private Integer type;
-
-    @Schema(description = "授权码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @NotEmpty(message = "授权码不能为空")
-    private String code;
-
-    @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
-    @NotEmpty(message = "state 不能为空")
-    private String state;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserPageReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserPageReqVO.java
deleted file mode 100644
index e422277..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserPageReqVO.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.user;
-
-import com.iailab.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - 社交用户分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SocialUserPageReqVO extends PageParam {
-
-    @Schema(description = "社交平台的类型", example = "30")
-    private Integer type;
-
-    @Schema(description = "用户昵称", example = "李四")
-    private String nickname;
-
-    @Schema(description = "社交 openid", example = "oz-Jdt0kd_jdhUxJHQdBJMlOFN7w")
-    private String openid;
-
-    @Schema(description = "创建时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] createTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java
deleted file mode 100644
index 07a0e34..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.user;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-@Schema(description = "管理后台 - 社交用户 Response VO")
-@Data
-public class SocialUserRespVO {
-
-    @Schema(description = "主键(自增策略)", requiredMode = Schema.RequiredMode.REQUIRED, example = "14569")
-    private Long id;
-
-    @Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
-    private Integer type;
-
-    @Schema(description = "社交 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
-    private String openid;
-
-    @Schema(description = "社交 token", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
-    private String token;
-
-    @Schema(description = "原始 Token 数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
-    private String rawTokenInfo;
-
-    @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "iailab")
-    private String nickname;
-
-    @Schema(description = "用户头像", example = "https://www.baidu.com/xxx.png")
-    private String avatar;
-
-    @Schema(description = "原始用户数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
-    private String rawUserInfo;
-
-    @Schema(description = "最后一次的认证 code", requiredMode = Schema.RequiredMode.REQUIRED, example = "666666")
-    private String code;
-
-    @Schema(description = "最后一次的认证 state", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
-    private String state;
-
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime createTime;
-
-    @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    private LocalDateTime updateTime;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserUnbindReqVO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserUnbindReqVO.java
deleted file mode 100644
index 40ca4fe..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/socail/vo/user/SocialUserUnbindReqVO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.iailab.module.system.controller.admin.socail.vo.user;
-
-import com.iailab.framework.common.validation.InEnum;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-@Schema(description = "管理后台 - 取消社交绑定 Request VO")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class SocialUserUnbindReqVO {
-
-    @Schema(description = "社交平台的类型,参见 UserSocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
-    @InEnum(SocialTypeEnum.class)
-    @NotNull(message = "社交平台的类型不能为空")
-    private Integer type;
-
-    @Schema(description = "社交用户的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
-    @NotEmpty(message = "社交用户的 openid 不能为空")
-    private String openid;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/user/UserProfileController.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/user/UserProfileController.java
index 339a1ce..ec1b766 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/user/UserProfileController.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/controller/admin/user/UserProfileController.java
@@ -1,7 +1,6 @@
 package com.iailab.module.system.controller.admin.user;
 
 import cn.hutool.core.collection.CollUtil;
-import com.iailab.framework.common.enums.UserTypeEnum;
 import com.iailab.framework.common.pojo.CommonResult;
 import com.iailab.framework.datapermission.core.annotation.DataPermission;
 import com.iailab.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
@@ -11,13 +10,11 @@
 import com.iailab.module.system.dal.dataobject.dept.DeptDO;
 import com.iailab.module.system.dal.dataobject.dept.PostDO;
 import com.iailab.module.system.dal.dataobject.permission.RoleDO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
 import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
 import com.iailab.module.system.service.dept.DeptService;
 import com.iailab.module.system.service.dept.PostService;
 import com.iailab.module.system.service.permission.PermissionService;
 import com.iailab.module.system.service.permission.RoleService;
-import com.iailab.module.system.service.social.SocialUserService;
 import com.iailab.module.system.service.user.AdminUserService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -52,8 +49,6 @@
     private PermissionService permissionService;
     @Resource
     private RoleService roleService;
-    @Resource
-    private SocialUserService socialService;
 
     @GetMapping("/get")
     @Operation(summary = "获得登录用户信息")
@@ -68,8 +63,7 @@
         // 获得岗位信息
         List<PostDO> posts = CollUtil.isNotEmpty(user.getPostIds()) ? postService.getPostList(user.getPostIds()) : null;
         // 获得社交用户信息
-        List<SocialUserDO> socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN.getValue());
-        return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts, socialUsers));
+        return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts));
     }
 
     @PutMapping("/update")
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/auth/AuthConvert.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/auth/AuthConvert.java
index 5315a17..a14b65d 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/auth/AuthConvert.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/auth/AuthConvert.java
@@ -2,8 +2,6 @@
 
 import cn.hutool.core.collection.CollUtil;
 import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
 import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
 import com.iailab.module.system.controller.admin.auth.vo.*;
 import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
@@ -218,9 +216,5 @@
     }
 
     SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO);
-
-    SmsCodeSendReqDTO convert(AuthSmsSendReqVO reqVO);
-
-    SmsCodeUseReqDTO convert(AuthSmsLoginReqVO reqVO, Integer scene, String usedIp);
 
 }
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/social/SocialUserConvert.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/social/SocialUserConvert.java
deleted file mode 100644
index 435c9f0..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/social/SocialUserConvert.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.iailab.module.system.convert.social;
-
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.factory.Mappers;
-
-@Mapper
-public interface SocialUserConvert {
-
-    SocialUserConvert INSTANCE = Mappers.getMapper(SocialUserConvert.class);
-
-    @Mapping(source = "reqVO.type", target = "socialType")
-    SocialUserBindReqDTO convert(Long userId, Integer userType, SocialUserBindReqVO reqVO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/user/UserConvert.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/user/UserConvert.java
index 3bbd788..2b19556 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/user/UserConvert.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/convert/user/UserConvert.java
@@ -12,7 +12,6 @@
 import com.iailab.module.system.dal.dataobject.dept.DeptDO;
 import com.iailab.module.system.dal.dataobject.dept.PostDO;
 import com.iailab.module.system.dal.dataobject.permission.RoleDO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
 import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -46,12 +45,11 @@
     }
 
     default UserProfileRespVO convert(AdminUserDO user, List<RoleDO> userRoles,
-                                      DeptDO dept, List<PostDO> posts, List<SocialUserDO> socialUsers) {
+                                      DeptDO dept, List<PostDO> posts) {
         UserProfileRespVO userVO = BeanUtils.toBean(user, UserProfileRespVO.class);
         userVO.setRoles(BeanUtils.toBean(userRoles, RoleSimpleRespVO.class));
         userVO.setDept(BeanUtils.toBean(dept, DeptSimpleRespVO.class));
         userVO.setPosts(BeanUtils.toBean(posts, PostSimpleRespVO.class));
-        userVO.setSocialUsers(BeanUtils.toBean(socialUsers, UserProfileRespVO.SocialUser.class));
         return userVO;
     }
 
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsChannelDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsChannelDO.java
deleted file mode 100644
index 9a9ec12..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsChannelDO.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.iailab.module.system.dal.dataobject.sms;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.iailab.module.system.framework.sms.core.enums.SmsChannelEnum;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-/**
- * 短信渠道 DO
- *
- * @author zzf
- * @since 2021-01-25
- */
-@TableName(value = "system_sms_channel", autoResultMap = true)
-@KeySequence("system_sms_channel_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SmsChannelDO extends BaseDO {
-
-    /**
-     * 渠道编号
-     */
-    private Long id;
-    /**
-     * 短信签名
-     */
-    private String signature;
-    /**
-     * 渠道编码
-     *
-     * 枚举 {@link SmsChannelEnum}
-     */
-    private String code;
-    /**
-     * 启用状态
-     *
-     * 枚举 {@link CommonStatusEnum}
-     */
-    private Integer status;
-    /**
-     * 备注
-     */
-    private String remark;
-    /**
-     * 短信 API 的账号
-     */
-    private String apiKey;
-    /**
-     * 短信 API 的密钥
-     */
-    private String apiSecret;
-    /**
-     * 短信发送回调 URL
-     */
-    private String callbackUrl;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsCodeDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsCodeDO.java
deleted file mode 100644
index f0417f3..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsCodeDO.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.iailab.module.system.dal.dataobject.sms;
-
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-import java.time.LocalDateTime;
-
-/**
- * 手机验证码 DO
- *
- * idx_mobile 索引:基于 {@link #mobile} 字段
- *
- * @author iailab
- */
-@TableName("system_sms_code")
-@KeySequence("system_sms_code_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SmsCodeDO extends BaseDO {
-
-    /**
-     * 编号
-     */
-    private Long id;
-    /**
-     * 手机号
-     */
-    private String mobile;
-    /**
-     * 验证码
-     */
-    private String code;
-    /**
-     * 发送场景
-     *
-     * 枚举 {@link SmsCodeDO}
-     */
-    private Integer scene;
-    /**
-     * 创建 IP
-     */
-    private String createIp;
-    /**
-     * 今日发送的第几条
-     */
-    private Integer todayIndex;
-    /**
-     * 是否使用
-     */
-    private Boolean used;
-    /**
-     * 使用时间
-     */
-    private LocalDateTime usedTime;
-    /**
-     * 使用 IP
-     */
-    private String usedIp;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsLogDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsLogDO.java
deleted file mode 100644
index a0b027c..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsLogDO.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.iailab.module.system.dal.dataobject.sms;
-
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.iailab.module.system.enums.sms.SmsReceiveStatusEnum;
-import com.iailab.module.system.enums.sms.SmsSendStatusEnum;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
-import lombok.*;
-
-import java.time.LocalDateTime;
-import java.util.Map;
-
-/**
- * 短信日志 DO
- *
- * @author zzf
- * @since 2021-01-25
- */
-@TableName(value = "system_sms_log", autoResultMap = true)
-@KeySequence("system_sms_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class SmsLogDO extends BaseDO {
-
-    /**
-     * 自增编号
-     */
-    private Long id;
-
-    // ========= 渠道相关字段 =========
-
-    /**
-     * 短信渠道编号
-     *
-     * 关联 {@link SmsChannelDO#getId()}
-     */
-    private Long channelId;
-    /**
-     * 短信渠道编码
-     *
-     * 冗余 {@link SmsChannelDO#getCode()}
-     */
-    private String channelCode;
-
-    // ========= 模板相关字段 =========
-
-    /**
-     * 模板编号
-     *
-     * 关联 {@link SmsTemplateDO#getId()}
-     */
-    private Long templateId;
-    /**
-     * 模板编码
-     *
-     * 冗余 {@link SmsTemplateDO#getCode()}
-     */
-    private String templateCode;
-    /**
-     * 短信类型
-     *
-     * 冗余 {@link SmsTemplateDO#getType()}
-     */
-    private Integer templateType;
-    /**
-     * 基于 {@link SmsTemplateDO#getContent()} 格式化后的内容
-     */
-    private String templateContent;
-    /**
-     * 基于 {@link SmsTemplateDO#getParams()} 输入后的参数
-     */
-    @TableField(typeHandler = JacksonTypeHandler.class)
-    private Map<String, Object> templateParams;
-    /**
-     * 短信 API 的模板编号
-     *
-     * 冗余 {@link SmsTemplateDO#getApiTemplateId()}
-     */
-    private String apiTemplateId;
-
-    // ========= 手机相关字段 =========
-
-    /**
-     * 手机号
-     */
-    private String mobile;
-    /**
-     * 用户编号
-     */
-    private Long userId;
-    /**
-     * 用户类型
-     *
-     * 枚举 {@link UserTypeEnum}
-     */
-    private Integer userType;
-
-    // ========= 发送相关字段 =========
-
-    /**
-     * 发送状态
-     *
-     * 枚举 {@link SmsSendStatusEnum}
-     */
-    private Integer sendStatus;
-    /**
-     * 发送时间
-     */
-    private LocalDateTime sendTime;
-    /**
-     * 短信 API 发送结果的编码
-     *
-     * 由于第三方的错误码可能是字符串,所以使用 String 类型
-     */
-    private String apiSendCode;
-    /**
-     * 短信 API 发送失败的提示
-     */
-    private String apiSendMsg;
-    /**
-     * 短信 API 发送返回的唯一请求 ID
-     *
-     * 用于和短信 API 进行定位于排错
-     */
-    private String apiRequestId;
-    /**
-     * 短信 API 发送返回的序号
-     *
-     * 用于和短信 API 平台的发送记录关联
-     */
-    private String apiSerialNo;
-
-    // ========= 接收相关字段 =========
-
-    /**
-     * 接收状态
-     *
-     * 枚举 {@link SmsReceiveStatusEnum}
-     */
-    private Integer receiveStatus;
-    /**
-     * 接收时间
-     */
-    private LocalDateTime receiveTime;
-    /**
-     * 短信 API 接收结果的编码
-     */
-    private String apiReceiveCode;
-    /**
-     * 短信 API 接收结果的提示
-     */
-    private String apiReceiveMsg;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsTemplateDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsTemplateDO.java
deleted file mode 100644
index 8fb046e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/sms/SmsTemplateDO.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.iailab.module.system.dal.dataobject.sms;
-
-import com.iailab.module.system.enums.sms.SmsTemplateTypeEnum;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-import java.util.List;
-
-/**
- * 短信模板 DO
- *
- * @author zzf
- * @since 2021-01-25
- */
-@TableName(value = "system_sms_template", autoResultMap = true)
-@KeySequence("system_sms_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class SmsTemplateDO extends BaseDO {
-
-    /**
-     * 自增编号
-     */
-    private Long id;
-
-    // ========= 模板相关字段 =========
-
-    /**
-     * 短信类型
-     *
-     * 枚举 {@link SmsTemplateTypeEnum}
-     */
-    private Integer type;
-    /**
-     * 启用状态
-     *
-     * 枚举 {@link CommonStatusEnum}
-     */
-    private Integer status;
-    /**
-     * 模板编码,保证唯一
-     */
-    private String code;
-    /**
-     * 模板名称
-     */
-    private String name;
-    /**
-     * 模板内容
-     *
-     * 内容的参数,使用 {} 包括,例如说 {name}
-     */
-    private String content;
-    /**
-     * 参数数组(自动根据内容生成)
-     */
-    @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<String> params;
-    /**
-     * 备注
-     */
-    private String remark;
-    /**
-     * 短信 API 的模板编号
-     */
-    private String apiTemplateId;
-
-    // ========= 渠道相关字段 =========
-
-    /**
-     * 短信渠道编号
-     *
-     * 关联 {@link SmsChannelDO#getId()}
-     */
-    private Long channelId;
-    /**
-     * 短信渠道编码
-     *
-     * 冗余 {@link SmsChannelDO#getCode()}
-     */
-    private String channelCode;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialClientDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialClientDO.java
deleted file mode 100644
index 53bf0b4..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialClientDO.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.iailab.module.system.dal.dataobject.social;
-
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.tenant.core.db.TenantBaseDO;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.xingyuv.jushauth.config.AuthConfig;
-import lombok.*;
-
-/**
- * 社交客户端 DO
- *
- * 对应 {@link AuthConfig} 配置,满足不同租户,有自己的客户端配置,实现社交(三方)登录
- *
- * @author iailab
- */
-@TableName(value = "system_social_client", autoResultMap = true)
-@KeySequence("system_social_client_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SocialClientDO extends TenantBaseDO {
-
-    /**
-     * 编号,自增
-     */
-    @TableId
-    private Long id;
-    /**
-     * 应用名
-     */
-    private String name;
-    /**
-     * 社交类型
-     *
-     * 枚举 {@link SocialTypeEnum}
-     */
-    private Integer socialType;
-    /**
-     * 用户类型
-     *
-     * 目的:不同用户类型,对应不同的小程序,需要自己的配置
-     *
-     * 枚举 {@link UserTypeEnum}
-     */
-    private Integer userType;
-    /**
-     * 状态
-     *
-     * 枚举 {@link CommonStatusEnum}
-     */
-    private Integer status;
-
-    /**
-     * 客户端 id
-     */
-    private String clientId;
-    /**
-     * 客户端 Secret
-     */
-    private String clientSecret;
-
-    /**
-     * 代理编号
-     *
-     * 目前只有部分“社交类型”在使用:
-     * 1. 企业微信:对应授权方的网页应用 ID
-     */
-    private String agentId;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialUserBindDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialUserBindDO.java
deleted file mode 100644
index 7f02ff2..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialUserBindDO.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.iailab.module.system.dal.dataobject.social;
-
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-/**
- * 社交用户的绑定
- * 即 {@link SocialUserDO} 与 UserDO 的关联表
- *
- * @author iailab
- */
-@TableName(value = "system_social_user_bind", autoResultMap = true)
-@KeySequence("system_social_user_bind_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SocialUserBindDO extends BaseDO {
-
-    /**
-     * 编号
-     */
-    @TableId
-    private Long id;
-    /**
-     * 关联的用户编号
-     *
-     * 关联 UserDO 的编号
-     */
-    private Long userId;
-    /**
-     * 用户类型
-     *
-     * 枚举 {@link UserTypeEnum}
-     */
-    private Integer userType;
-
-    /**
-     * 社交平台的用户编号
-     *
-     * 关联 {@link SocialUserDO#getId()}
-     */
-    private Long socialUserId;
-    /**
-     * 社交平台的类型
-     *
-     * 冗余 {@link SocialUserDO#getType()}
-     */
-    private Integer socialType;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialUserDO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialUserDO.java
deleted file mode 100644
index 3847f07..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/dataobject/social/SocialUserDO.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.iailab.module.system.dal.dataobject.social;
-
-import com.iailab.framework.mybatis.core.dataobject.BaseDO;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.*;
-
-/**
- * 社交(三方)用户
- *
- * @author weir
- */
-@TableName(value = "system_social_user", autoResultMap = true)
-@KeySequence("system_social_user_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
-@Data
-@EqualsAndHashCode(callSuper = true)
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SocialUserDO extends BaseDO {
-
-    /**
-     * 自增主键
-     */
-    @TableId
-    private Long id;
-    /**
-     * 社交平台的类型
-     *
-     * 枚举 {@link SocialTypeEnum}
-     */
-    private Integer type;
-
-    /**
-     * 社交 openid
-     */
-    private String openid;
-    /**
-     * 社交 token
-     */
-    private String token;
-    /**
-     * 原始 Token 数据,一般是 JSON 格式
-     */
-    private String rawTokenInfo;
-
-    /**
-     * 用户昵称
-     */
-    private String nickname;
-    /**
-     * 用户头像
-     */
-    private String avatar;
-    /**
-     * 原始用户数据,一般是 JSON 格式
-     */
-    private String rawUserInfo;
-
-    /**
-     * 最后一次的认证 code
-     */
-    private String code;
-    /**
-     * 最后一次的认证 state
-     */
-    private String state;
-
-}
-
-
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsChannelMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsChannelMapper.java
deleted file mode 100644
index 48c4cdf..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsChannelMapper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.module.system.dal.mysql.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
-
-    default PageResult<SmsChannelDO> selectPage(SmsChannelPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<SmsChannelDO>()
-                .likeIfPresent(SmsChannelDO::getSignature, reqVO.getSignature())
-                .eqIfPresent(SmsChannelDO::getStatus, reqVO.getStatus())
-                .betweenIfPresent(SmsChannelDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(SmsChannelDO::getId));
-    }
-
-    default SmsChannelDO selectByCode(String code) {
-        return selectOne(SmsChannelDO::getCode, code);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsCodeMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsCodeMapper.java
deleted file mode 100644
index a0e8dab..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsCodeMapper.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.module.system.dal.mysql.sms;
-
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.QueryWrapperX;
-import com.iailab.module.system.dal.dataobject.sms.SmsCodeDO;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SmsCodeMapper extends BaseMapperX<SmsCodeDO> {
-
-    /**
-     * 获得手机号的最后一个手机验证码
-     *
-     * @param mobile 手机号
-     * @param scene 发送场景,选填
-     * @param code 验证码 选填
-     * @return 手机验证码
-     */
-    default SmsCodeDO selectLastByMobile(String mobile, String code, Integer scene) {
-        return selectOne(new QueryWrapperX<SmsCodeDO>()
-                .eq("mobile", mobile)
-                .eqIfPresent("scene", scene)
-                .eqIfPresent("code", code)
-                .orderByDesc("id")
-                .limitN(1));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsLogMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsLogMapper.java
deleted file mode 100644
index d1b7252..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsLogMapper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.iailab.module.system.dal.mysql.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.iailab.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsLogDO;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SmsLogMapper extends BaseMapperX<SmsLogDO> {
-
-    default PageResult<SmsLogDO> selectPage(SmsLogPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<SmsLogDO>()
-                .eqIfPresent(SmsLogDO::getChannelId, reqVO.getChannelId())
-                .eqIfPresent(SmsLogDO::getTemplateId, reqVO.getTemplateId())
-                .likeIfPresent(SmsLogDO::getMobile, reqVO.getMobile())
-                .eqIfPresent(SmsLogDO::getSendStatus, reqVO.getSendStatus())
-                .betweenIfPresent(SmsLogDO::getSendTime, reqVO.getSendTime())
-                .eqIfPresent(SmsLogDO::getReceiveStatus, reqVO.getReceiveStatus())
-                .betweenIfPresent(SmsLogDO::getReceiveTime, reqVO.getReceiveTime())
-                .orderByDesc(SmsLogDO::getId));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsTemplateMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsTemplateMapper.java
deleted file mode 100644
index 98789e5..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/sms/SmsTemplateMapper.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.iailab.module.system.dal.mysql.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> {
-
-    default SmsTemplateDO selectByCode(String code) {
-        return selectOne(SmsTemplateDO::getCode, code);
-    }
-
-    default PageResult<SmsTemplateDO> selectPage(SmsTemplatePageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<SmsTemplateDO>()
-                .eqIfPresent(SmsTemplateDO::getType, reqVO.getType())
-                .eqIfPresent(SmsTemplateDO::getStatus, reqVO.getStatus())
-                .likeIfPresent(SmsTemplateDO::getCode, reqVO.getCode())
-                .likeIfPresent(SmsTemplateDO::getContent, reqVO.getContent())
-                .likeIfPresent(SmsTemplateDO::getApiTemplateId, reqVO.getApiTemplateId())
-                .eqIfPresent(SmsTemplateDO::getChannelId, reqVO.getChannelId())
-                .betweenIfPresent(SmsTemplateDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(SmsTemplateDO::getId));
-    }
-
-    default Long selectCountByChannelId(Long channelId) {
-        return selectCount(SmsTemplateDO::getChannelId, channelId);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialClientMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialClientMapper.java
deleted file mode 100644
index 8110e24..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialClientMapper.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.iailab.module.system.dal.mysql.social;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialClientDO;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SocialClientMapper extends BaseMapperX<SocialClientDO> {
-
-    default SocialClientDO selectBySocialTypeAndUserType(Integer socialType, Integer userType) {
-        return selectOne(SocialClientDO::getSocialType, socialType,
-                SocialClientDO::getUserType, userType);
-    }
-
-    default PageResult<SocialClientDO> selectPage(SocialClientPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<SocialClientDO>()
-                .likeIfPresent(SocialClientDO::getName, reqVO.getName())
-                .eqIfPresent(SocialClientDO::getSocialType, reqVO.getSocialType())
-                .eqIfPresent(SocialClientDO::getUserType, reqVO.getUserType())
-                .likeIfPresent(SocialClientDO::getClientId, reqVO.getClientId())
-                .eqIfPresent(SocialClientDO::getStatus, reqVO.getStatus())
-                .orderByDesc(SocialClientDO::getId));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialUserBindMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialUserBindMapper.java
deleted file mode 100644
index 0ba92b5..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialUserBindMapper.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.iailab.module.system.dal.mysql.social;
-
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.iailab.module.system.dal.dataobject.social.SocialUserBindDO;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-
-@Mapper
-public interface SocialUserBindMapper extends BaseMapperX<SocialUserBindDO> {
-
-    default void deleteByUserTypeAndUserIdAndSocialType(Integer userType, Long userId, Integer socialType) {
-        delete(new LambdaQueryWrapperX<SocialUserBindDO>()
-                .eq(SocialUserBindDO::getUserType, userType)
-                .eq(SocialUserBindDO::getUserId, userId)
-                .eq(SocialUserBindDO::getSocialType, socialType));
-    }
-
-    default void deleteByUserTypeAndSocialUserId(Integer userType, Long socialUserId) {
-        delete(new LambdaQueryWrapperX<SocialUserBindDO>()
-                .eq(SocialUserBindDO::getUserType, userType)
-                .eq(SocialUserBindDO::getSocialUserId, socialUserId));
-    }
-
-    default SocialUserBindDO selectByUserTypeAndSocialUserId(Integer userType, Long socialUserId) {
-        return selectOne(SocialUserBindDO::getUserType, userType,
-                SocialUserBindDO::getSocialUserId, socialUserId);
-    }
-
-    default List<SocialUserBindDO> selectListByUserIdAndUserType(Long userId, Integer userType) {
-        return selectList(new LambdaQueryWrapperX<SocialUserBindDO>()
-                .eq(SocialUserBindDO::getUserId, userId)
-                .eq(SocialUserBindDO::getUserType, userType));
-    }
-
-    default SocialUserBindDO selectByUserIdAndUserTypeAndSocialType(Long userId, Integer userType, Integer socialType) {
-        return selectOne(new LambdaQueryWrapperX<SocialUserBindDO>()
-                .eq(SocialUserBindDO::getUserId, userId)
-                .eq(SocialUserBindDO::getUserType, userType)
-                .eq(SocialUserBindDO::getSocialType, socialType));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialUserMapper.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialUserMapper.java
deleted file mode 100644
index 9a801fb..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/social/SocialUserMapper.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.module.system.dal.mysql.social;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
-import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import org.apache.ibatis.annotations.Mapper;
-
-@Mapper
-public interface SocialUserMapper extends BaseMapperX<SocialUserDO> {
-
-    default SocialUserDO selectByTypeAndCodeAnState(Integer type, String code, String state) {
-        return selectOne(new LambdaQueryWrapper<SocialUserDO>()
-                .eq(SocialUserDO::getType, type)
-                .eq(SocialUserDO::getCode, code)
-                .eq(SocialUserDO::getState, state));
-    }
-
-    default SocialUserDO selectByTypeAndOpenid(Integer type, String openid) {
-        return selectOne(new LambdaQueryWrapper<SocialUserDO>()
-                .eq(SocialUserDO::getType, type)
-                .eq(SocialUserDO::getOpenid, openid));
-    }
-
-    default PageResult<SocialUserDO> selectPage(SocialUserPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<SocialUserDO>()
-                .eqIfPresent(SocialUserDO::getType, reqVO.getType())
-                .likeIfPresent(SocialUserDO::getNickname, reqVO.getNickname())
-                .likeIfPresent(SocialUserDO::getOpenid, reqVO.getOpenid())
-                .betweenIfPresent(SocialUserDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(SocialUserDO::getId));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/rpc/config/RpcConfiguration.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/rpc/config/RpcConfiguration.java
index 751584e..c71cb83 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/rpc/config/RpcConfiguration.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/rpc/config/RpcConfiguration.java
@@ -3,12 +3,13 @@
 import com.iailab.module.infra.api.config.ConfigApi;
 import com.iailab.module.infra.api.db.DataSourceConfigServiceApi;
 import com.iailab.module.infra.api.file.FileApi;
+import com.iailab.module.infra.api.monitor.MonitorApi;
 import com.iailab.module.infra.api.websocket.WebSocketSenderApi;
 import com.iailab.module.system.api.tenant.TenantApi;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.Configuration;
 
 @Configuration(proxyBeanMethods = false)
-@EnableFeignClients(clients = {FileApi.class, WebSocketSenderApi.class, DataSourceConfigServiceApi.class, ConfigApi.class, TenantApi.class})
+@EnableFeignClients(clients = {FileApi.class, MonitorApi.class, WebSocketSenderApi.class, DataSourceConfigServiceApi.class, ConfigApi.class, TenantApi.class})
 public class RpcConfiguration {
 }
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/config/SmsCodeProperties.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/config/SmsCodeProperties.java
deleted file mode 100644
index a6c68b5..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/config/SmsCodeProperties.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.iailab.module.system.framework.sms.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-import javax.validation.constraints.NotNull;
-import java.time.Duration;
-
-@ConfigurationProperties(prefix = "iailab.sms-code")
-@Validated
-@Data
-public class SmsCodeProperties {
-
-    /**
-     * 过期时间
-     */
-    @NotNull(message = "过期时间不能为空")
-    private Duration expireTimes;
-    /**
-     * 短信发送频率
-     */
-    @NotNull(message = "短信发送频率不能为空")
-    private Duration sendFrequency;
-    /**
-     * 每日发送最大数量
-     */
-    @NotNull(message = "每日发送最大数量不能为空")
-    private Integer sendMaximumQuantityPerDay;
-    /**
-     * 验证码最小值
-     */
-    @NotNull(message = "验证码最小值不能为空")
-    private Integer beginCode;
-    /**
-     * 验证码最大值
-     */
-    @NotNull(message = "验证码最大值不能为空")
-    private Integer endCode;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/config/SmsConfiguration.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/config/SmsConfiguration.java
deleted file mode 100644
index b193136..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/config/SmsConfiguration.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.iailab.module.system.framework.sms.config;
-
-import com.iailab.module.system.framework.sms.core.client.SmsClientFactory;
-import com.iailab.module.system.framework.sms.core.client.impl.SmsClientFactoryImpl;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 短信配置类,包括短信客户端、短信验证码两部分
- *
- * @author iailab
- */
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(SmsCodeProperties.class)
-public class SmsConfiguration {
-
-    @Bean
-    public SmsClientFactory smsClientFactory() {
-        return new SmsClientFactoryImpl();
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/SmsClient.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/SmsClient.java
deleted file mode 100644
index af964bb..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/SmsClient.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client;
-
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-
-import java.util.List;
-
-/**
- * 短信客户端,用于对接各短信平台的 SDK,实现短信发送等功能
- *
- * @author zzf
- * @since 2021/1/25 14:14
- */
-public interface SmsClient {
-
-    /**
-     * 获得渠道编号
-     *
-     * @return 渠道编号
-     */
-    Long getId();
-
-    /**
-     * 发送消息
-     *
-     * @param logId 日志编号
-     * @param mobile 手机号
-     * @param apiTemplateId 短信 API 的模板编号
-     * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序
-     * @return 短信发送结果
-     */
-    SmsSendRespDTO sendSms(Long logId, String mobile, String apiTemplateId,
-                           List<KeyValue<String, Object>> templateParams) throws Throwable;
-
-    /**
-     * 解析接收短信的接收结果
-     *
-     * @param text 结果
-     * @return 结果内容
-     * @throws Throwable 当解析 text 发生异常时,则会抛出异常
-     */
-    List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
-
-    /**
-     * 查询指定的短信模板
-     *
-     * @param apiTemplateId 短信 API 的模板编号
-     * @return 短信模板
-     */
-    SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/SmsClientFactory.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/SmsClientFactory.java
deleted file mode 100644
index f3f7e9e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/SmsClientFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client;
-
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-
-/**
- * 短信客户端的工厂接口
- *
- * @author zzf
- * @since 2021/1/28 14:01
- */
-public interface SmsClientFactory {
-
-    /**
-     * 获得短信 Client
-     *
-     * @param channelId 渠道编号
-     * @return 短信 Client
-     */
-    SmsClient getSmsClient(Long channelId);
-
-    /**
-     * 获得短信 Client
-     *
-     * @param channelCode 渠道编码
-     * @return 短信 Client
-     */
-    SmsClient getSmsClient(String channelCode);
-
-    /**
-     * 创建短信 Client
-     *
-     * @param properties 配置对象
-     */
-    void createOrUpdateSmsClient(SmsChannelProperties properties);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java
deleted file mode 100644
index 03c0c25..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.dto;
-
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * 消息接收 Response DTO
- *
- * @author iailab
- */
-@Data
-public class SmsReceiveRespDTO {
-
-    /**
-     * 是否接收成功
-     */
-    private Boolean success;
-    /**
-     * API 接收结果的编码
-     */
-    private String errorCode;
-    /**
-     * API 接收结果的说明
-     */
-    private String errorMsg;
-
-    /**
-     * 手机号
-     */
-    private String mobile;
-    /**
-     * 用户接收时间
-     */
-    private LocalDateTime receiveTime;
-
-    /**
-     * 短信 API 发送返回的序号
-     */
-    private String serialNo;
-    /**
-     * 短信日志编号
-     *
-     * 对应 SysSmsLogDO 的编号
-     */
-    private Long logId;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java
deleted file mode 100644
index b47e08e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.dto;
-
-import lombok.Data;
-
-/**
- * 短信发送 Response DTO
- *
- * @author iailab
- */
-@Data
-public class SmsSendRespDTO {
-
-    /**
-     * 是否成功
-     */
-    private Boolean success;
-
-    /**
-     * API 请求编号
-     */
-    private String apiRequestId;
-
-    // ==================== 成功时字段 ====================
-
-    /**
-     * 短信 API 发送返回的序号
-     */
-    private String serialNo;
-
-    // ==================== 失败时字段 ====================
-
-    /**
-     * API 返回错误码
-     *
-     * 由于第三方的错误码可能是字符串,所以使用 String 类型
-     */
-    private String apiCode;
-    /**
-     * API 返回提示
-     */
-    private String apiMsg;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java
deleted file mode 100644
index 6c23252..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.dto;
-
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import lombok.Data;
-
-/**
- * 短信模板 Response DTO
- *
- * @author iailab
- */
-@Data
-public class SmsTemplateRespDTO {
-
-    /**
-     * 模板编号
-     */
-    private String id;
-    /**
-     * 短信内容
-     */
-    private String content;
-    /**
-     * 审核状态
-     *
-     * 枚举 {@link SmsTemplateAuditStatusEnum}
-     */
-    private Integer auditStatus;
-    /**
-     * 审核未通过的理由
-     */
-    private String auditReason;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/AbstractSmsClient.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/AbstractSmsClient.java
deleted file mode 100644
index d50e30b..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/AbstractSmsClient.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 短信客户端的抽象类,提供模板方法,减少子类的冗余代码
- *
- * @author zzf
- * @since 2021/2/1 9:28
- */
-@Slf4j
-public abstract class AbstractSmsClient implements SmsClient {
-
-    /**
-     * 短信渠道配置
-     */
-    protected volatile SmsChannelProperties properties;
-
-    public AbstractSmsClient(SmsChannelProperties properties) {
-        this.properties = properties;
-    }
-
-    /**
-     * 初始化
-     */
-    public final void init() {
-        doInit();
-        log.debug("[init][配置({}) 初始化完成]", properties);
-    }
-
-    /**
-     * 自定义初始化
-     */
-    protected abstract void doInit();
-
-    public final void refresh(SmsChannelProperties properties) {
-        // 判断是否更新
-        if (properties.equals(this.properties)) {
-            return;
-        }
-        log.info("[refresh][配置({})发生变化,重新初始化]", properties);
-        this.properties = properties;
-        // 初始化
-        this.init();
-    }
-
-    @Override
-    public Long getId() {
-        return properties.getId();
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/AliyunSmsClient.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/AliyunSmsClient.java
deleted file mode 100644
index a3f2ab2..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/AliyunSmsClient.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import cn.hutool.core.lang.Assert;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.util.collection.MapUtils;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.client.impl.AbstractSmsClient;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
-import com.aliyuncs.profile.DefaultProfile;
-import com.aliyuncs.profile.IClientProfile;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.annotations.VisibleForTesting;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Objects;
-
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
-import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-import static com.iailab.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
-
-/**
- * 阿里短信客户端的实现类
- *
- * @author zzf
- * @since 2021/1/25 14:17
- */
-@Slf4j
-public class AliyunSmsClient extends AbstractSmsClient {
-
-    /**
-     * 调用成功 code
-     */
-    public static final String API_CODE_SUCCESS = "OK";
-
-    /**
-     * REGION, 使用杭州
-     */
-    private static final String ENDPOINT = "cn-hangzhou";
-
-    /**
-     * 阿里云客户端
-     */
-    private volatile IAcsClient client;
-
-    public AliyunSmsClient(SmsChannelProperties properties) {
-        super(properties);
-        Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
-        Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
-    }
-
-    @Override
-    protected void doInit() {
-        IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret());
-        client = new DefaultAcsClient(profile);
-    }
-
-    @Override
-    public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId,
-                                  List<KeyValue<String, Object>> templateParams) throws Throwable {
-        // 构建请求
-        SendSmsRequest request = new SendSmsRequest();
-        request.setPhoneNumbers(mobile);
-        request.setSignName(properties.getSignature());
-        request.setTemplateCode(apiTemplateId);
-        request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams)));
-        request.setOutId(String.valueOf(sendLogId));
-        // 执行请求
-        SendSmsResponse response = client.getAcsResponse(request);
-        return new SmsSendRespDTO().setSuccess(Objects.equals(response.getCode(), API_CODE_SUCCESS)).setSerialNo(response.getBizId())
-                .setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage());
-    }
-
-    @Override
-    public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
-        List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class);
-        return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess())
-                .setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg())
-                .setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime())
-                .setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId())));
-    }
-
-    @Override
-    public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable {
-        // 构建请求
-        QuerySmsTemplateRequest request = new QuerySmsTemplateRequest();
-        request.setTemplateCode(apiTemplateId);
-        // 执行请求
-        QuerySmsTemplateResponse response = client.getAcsResponse(request);
-        if (response.getTemplateStatus() == null) {
-            return null;
-        }
-        return new SmsTemplateRespDTO().setId(response.getTemplateCode()).setContent(response.getTemplateContent())
-                .setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason());
-    }
-
-    @VisibleForTesting
-    Integer convertSmsTemplateAuditStatus(Integer templateStatus) {
-        switch (templateStatus) {
-            case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
-            case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
-            case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
-            default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
-        }
-    }
-
-    /**
-     * 短信接收状态
-     *
-     * 参见 <a href="https://help.aliyun.com/document_detail/101867.html">文档</a>
-     *
-     * @author iailab
-     */
-    @Data
-    public static class SmsReceiveStatus {
-
-        /**
-         * 手机号
-         */
-        @JsonProperty("phone_number")
-        private String phoneNumber;
-        /**
-         * 发送时间
-         */
-        @JsonProperty("send_time")
-        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
-        private LocalDateTime sendTime;
-        /**
-         * 状态报告时间
-         */
-        @JsonProperty("report_time")
-        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
-        private LocalDateTime reportTime;
-        /**
-         * 是否接收成功
-         */
-        private Boolean success;
-        /**
-         * 状态报告说明
-         */
-        @JsonProperty("err_msg")
-        private String errMsg;
-        /**
-         * 状态报告编码
-         */
-        @JsonProperty("err_code")
-        private String errCode;
-        /**
-         * 发送序列号
-         */
-        @JsonProperty("biz_id")
-        private String bizId;
-        /**
-         * 用户序列号
-         *
-         * 这里我们传递的是 SysSmsLogDO 的日志编号
-         */
-        @JsonProperty("out_id")
-        private String outId;
-        /**
-         * 短信长度,例如说 1、2、3
-         *
-         * 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送
-         */
-        @JsonProperty("sms_size")
-        private Integer smsSize;
-
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java
deleted file mode 100644
index 33bbfd2..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import cn.hutool.core.codec.Base64;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.crypto.digest.DigestUtil;
-import cn.hutool.crypto.digest.HmacAlgorithm;
-import cn.hutool.http.HttpUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.util.collection.MapUtils;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.client.impl.AbstractSmsClient;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * 基于钉钉 WebHook 实现的调试的短信客户端实现类
- *
- * 考虑到省钱,我们使用钉钉 WebHook 模拟发送短信,方便调试。
- *
- * @author iailab
- */
-public class DebugDingTalkSmsClient extends AbstractSmsClient {
-
-    public DebugDingTalkSmsClient(SmsChannelProperties properties) {
-        super(properties);
-        Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
-        Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
-    }
-
-    @Override
-    protected void doInit() {
-    }
-
-    @Override
-    public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
-                                  String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
-        // 构建请求
-        String url = buildUrl("robot/send");
-        Map<String, Object> params = new HashMap<>();
-        params.put("msgtype", "text");
-        String content = String.format("【模拟短信】\n手机号:%s\n短信日志编号:%d\n模板参数:%s",
-                mobile, sendLogId, MapUtils.convertMap(templateParams));
-        params.put("text", MapUtil.builder().put("content", content).build());
-        // 执行请求
-        String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params));
-        // 解析结果
-        Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class);
-        String errorCode = MapUtil.getStr(responseObj, "errcode");
-        return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid())
-                .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg"));
-    }
-
-    /**
-     * 构建请求地址
-     *
-     * 参见 <a href="https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71">文档</a>
-     *
-     * @param path 请求路径
-     * @return 请求地址
-     */
-    @SuppressWarnings("SameParameterValue")
-    private String buildUrl(String path) {
-        // 生成 timestamp
-        long timestamp = System.currentTimeMillis();
-        // 生成 sign
-        String secret = properties.getApiSecret();
-        String stringToSign = timestamp + "\n" + secret;
-        byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign);
-        String sign = Base64.encode(signData);
-        // 构建最终 URL
-        return String.format("https://oapi.dingtalk.com/%s?access_token=%s&timestamp=%d&sign=%s",
-                path, properties.getApiKey(), timestamp, sign);
-    }
-
-    @Override
-    public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
-        throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调");
-    }
-
-    @Override
-    public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) {
-        return new SmsTemplateRespDTO().setId(apiTemplateId).setContent("")
-                .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason("");
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java
deleted file mode 100644
index ab4bb20..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.SmsClientFactory;
-import com.iailab.module.system.framework.sms.core.enums.SmsChannelEnum;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.Assert;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Arrays;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * 短信客户端工厂接口
- *
- * @author zzf
- */
-@Validated
-@Slf4j
-public class SmsClientFactoryImpl implements SmsClientFactory {
-
-    /**
-     * 短信客户端 Map
-     * key:渠道编号,使用 {@link SmsChannelProperties#getId()}
-     */
-    private final ConcurrentMap<Long, AbstractSmsClient> channelIdClients = new ConcurrentHashMap<>();
-
-    /**
-     * 短信客户端 Map
-     * key:渠道编码,使用 {@link SmsChannelProperties#getCode()} ()}
-     *
-     * 注意,一些场景下,需要获得某个渠道类型的客户端,所以需要使用它。
-     * 例如说,解析短信接收结果,是相对通用的,不需要使用某个渠道编号的 {@link #channelIdClients}
-     */
-    private final ConcurrentMap<String, AbstractSmsClient> channelCodeClients = new ConcurrentHashMap<>();
-
-    public SmsClientFactoryImpl() {
-        // 初始化 channelCodeClients 集合
-        Arrays.stream(SmsChannelEnum.values()).forEach(channel -> {
-            // 创建一个空的 SmsChannelProperties 对象
-            SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode())
-                    .setApiKey("default default").setApiSecret("default");
-            // 创建 Sms 客户端
-            AbstractSmsClient smsClient = createSmsClient(properties);
-            channelCodeClients.put(channel.getCode(), smsClient);
-        });
-    }
-
-    @Override
-    public SmsClient getSmsClient(Long channelId) {
-        return channelIdClients.get(channelId);
-    }
-
-    @Override
-    public SmsClient getSmsClient(String channelCode) {
-        return channelCodeClients.get(channelCode);
-    }
-
-    @Override
-    public void createOrUpdateSmsClient(SmsChannelProperties properties) {
-        AbstractSmsClient client = channelIdClients.get(properties.getId());
-        if (client == null) {
-            client = this.createSmsClient(properties);
-            client.init();
-            channelIdClients.put(client.getId(), client);
-        } else {
-            client.refresh(properties);
-        }
-    }
-
-    private AbstractSmsClient createSmsClient(SmsChannelProperties properties) {
-        SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(properties.getCode());
-        Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channelEnum));
-        // 创建客户端
-        switch (channelEnum) {
-            case ALIYUN: return new AliyunSmsClient(properties);
-            case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties);
-            case TENCENT: return new TencentSmsClient(properties);
-        }
-        // 创建失败,错误日志 + 抛出异常
-        log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties);
-        throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", properties));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/TencentSmsClient.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/TencentSmsClient.java
deleted file mode 100644
index 4dea4f7..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/client/impl/TencentSmsClient.java
+++ /dev/null
@@ -1,219 +0,0 @@
-package com.iailab.module.system.framework.sms.core.client.impl;
-
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.util.collection.ArrayUtils;
-import com.iailab.framework.common.util.json.JsonUtils;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.client.impl.AbstractSmsClient;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.annotations.VisibleForTesting;
-import com.tencentcloudapi.common.Credential;
-import com.tencentcloudapi.sms.v20210111.SmsClient;
-import com.tencentcloudapi.sms.v20210111.models.*;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Objects;
-
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
-import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-import static com.iailab.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
-
-/**
- * 腾讯云短信功能实现
- *
- * 参见 <a href="https://cloud.tencent.com/document/product/382/52077">文档</a>
- *
- * @author shiwp
- */
-public class TencentSmsClient extends AbstractSmsClient {
-
-    /**
-     * 调用成功 code
-     */
-    public static final String API_CODE_SUCCESS = "Ok";
-
-    /**
-     * REGION,使用南京
-     */
-    private static final String ENDPOINT = "ap-nanjing";
-
-    /**
-     * 是否国际/港澳台短信:
-     *
-     * 0:表示国内短信。
-     * 1:表示国际/港澳台短信。
-     */
-    private static final long INTERNATIONAL_CHINA = 0L;
-
-    private SmsClient client;
-
-    public TencentSmsClient(SmsChannelProperties properties) {
-        super(properties);
-        Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
-        validateSdkAppId(properties);
-    }
-
-    @Override
-    protected void doInit() {
-        // 实例化一个认证对象,入参需要传入腾讯云账户密钥对 secretId,secretKey
-        Credential credential = new Credential(getApiKey(), properties.getApiSecret());
-        client = new SmsClient(credential, ENDPOINT);
-    }
-
-    /**
-     * 参数校验腾讯云的 SDK AppId
-     *
-     * 原因是:腾讯云发放短信的时候,需要额外的参数 sdkAppId
-     *
-     * 解决方案:考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。
-     *
-     * @param properties 配置
-     */
-    private static void validateSdkAppId(SmsChannelProperties properties) {
-        String combineKey = properties.getApiKey();
-        Assert.notEmpty(combineKey, "apiKey 不能为空");
-        String[] keys = combineKey.trim().split(" ");
-        Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]");
-    }
-
-    private String getSdkAppId() {
-        return StrUtil.subAfter(properties.getApiKey(), " ", true);
-    }
-
-    private String getApiKey() {
-        return StrUtil.subBefore(properties.getApiKey(), " ", true);
-    }
-
-    @Override
-    public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
-                                  String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
-        // 构建请求
-        SendSmsRequest request = new SendSmsRequest();
-        request.setSmsSdkAppId(getSdkAppId());
-        request.setPhoneNumberSet(new String[]{mobile});
-        request.setSignName(properties.getSignature());
-        request.setTemplateId(apiTemplateId);
-        request.setTemplateParamSet(ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue())));
-        request.setSessionContext(JsonUtils.toJsonString(new SessionContext().setLogId(sendLogId)));
-        // 执行请求
-        SendSmsResponse response = client.SendSms(request);
-        SendStatus status = response.getSendStatusSet()[0];
-        return new SmsSendRespDTO().setSuccess(Objects.equals(status.getCode(), API_CODE_SUCCESS)).setSerialNo(status.getSerialNo())
-                .setApiRequestId(response.getRequestId()).setApiCode(status.getCode()).setApiMsg(status.getMessage());
-    }
-
-    @Override
-    public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
-        List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class);
-        return convertList(callback, status -> new SmsReceiveRespDTO()
-                .setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus()))
-                .setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription())
-                .setMobile(status.getMobile()).setReceiveTime(status.getReceiveTime())
-                .setSerialNo(status.getSerialNo()).setLogId(status.getSessionContext().getLogId()));
-    }
-
-    @Override
-    public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable {
-        // 构建请求
-        DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest();
-        request.setTemplateIdSet(new Long[]{Long.parseLong(apiTemplateId)});
-        request.setInternational(INTERNATIONAL_CHINA);
-        // 执行请求
-        DescribeSmsTemplateListResponse response = client.DescribeSmsTemplateList(request);
-        DescribeTemplateListStatus status = response.getDescribeTemplateStatusSet()[0];
-        if (status == null || status.getStatusCode() == null) {
-            return null;
-        }
-        return new SmsTemplateRespDTO().setId(status.getTemplateId().toString()).setContent(status.getTemplateContent())
-                .setAuditStatus(convertSmsTemplateAuditStatus(status.getStatusCode().intValue())).setAuditReason(status.getReviewReply());
-    }
-
-    @VisibleForTesting
-    Integer convertSmsTemplateAuditStatus(int templateStatus) {
-        switch (templateStatus) {
-            case 1: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
-            case 0: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
-            case -1: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
-            default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
-        }
-    }
-
-    @Data
-    private static class SmsReceiveStatus {
-
-        /**
-         * 短信接受成功 code
-         */
-        public static final String SUCCESS_CODE = "SUCCESS";
-
-        /**
-         * 用户实际接收到短信的时间
-         */
-        @JsonProperty("user_receive_time")
-        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
-        private LocalDateTime receiveTime;
-
-        /**
-         * 国家(或地区)码
-         */
-        @JsonProperty("nationcode")
-        private String nationCode;
-
-        /**
-         * 手机号码
-         */
-        private String mobile;
-
-        /**
-         * 实际是否收到短信接收状态,SUCCESS(成功)、FAIL(失败)
-         */
-        @JsonProperty("report_status")
-        private String status;
-
-        /**
-         * 用户接收短信状态码错误信息
-         */
-        @JsonProperty("errmsg")
-        private String errCode;
-
-        /**
-         * 用户接收短信状态描述
-         */
-        @JsonProperty("description")
-        private String description;
-
-        /**
-         * 本次发送标识 ID(与发送接口返回的SerialNo对应)
-         */
-        @JsonProperty("sid")
-        private String serialNo;
-
-        /**
-         * 用户的 session 内容(与发送接口的请求参数 SessionContext 一致)
-         */
-        @JsonProperty("ext")
-        private SessionContext sessionContext;
-
-    }
-
-    @VisibleForTesting
-    @Data
-    static class SessionContext {
-
-        /**
-         * 发送短信记录id
-         */
-        private Long logId;
-
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/enums/SmsChannelEnum.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/enums/SmsChannelEnum.java
deleted file mode 100644
index 878d3c1..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/enums/SmsChannelEnum.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.iailab.module.system.framework.sms.core.enums;
-
-import cn.hutool.core.util.ArrayUtil;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 短信渠道枚举
- *
- * @author zzf
- * @since 2021/1/25 10:56
- */
-@Getter
-@AllArgsConstructor
-public enum SmsChannelEnum {
-
-    DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"),
-    ALIYUN("ALIYUN", "阿里云"),
-    TENCENT("TENCENT", "腾讯云"),
-//    HUA_WEI("HUA_WEI", "华为云"),
-    ;
-
-    /**
-     * 编码
-     */
-    private final String code;
-    /**
-     * 名字
-     */
-    private final String name;
-
-    public static SmsChannelEnum getByCode(String code) {
-        return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java
deleted file mode 100644
index c550ce1..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.iailab.module.system.framework.sms.core.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 短信模板的审核状态枚举
- *
- * @author iailab
- */
-@AllArgsConstructor
-@Getter
-public enum SmsTemplateAuditStatusEnum {
-
-    CHECKING(1),
-    SUCCESS(2),
-    FAIL(3);
-
-    private final Integer status;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/property/SmsChannelProperties.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/property/SmsChannelProperties.java
deleted file mode 100644
index 410a78e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/framework/sms/core/property/SmsChannelProperties.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.iailab.module.system.framework.sms.core.property;
-
-import com.iailab.module.system.framework.sms.core.enums.SmsChannelEnum;
-import lombok.Data;
-import org.springframework.validation.annotation.Validated;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
-
-/**
- * 短信渠道配置类
- *
- * @author zzf
- * @since 2021/1/25 17:01
- */
-@Data
-@Validated
-public class SmsChannelProperties {
-
-    /**
-     * 渠道编号
-     */
-    @NotNull(message = "短信渠道 ID 不能为空")
-    private Long id;
-    /**
-     * 短信签名
-     */
-    @NotEmpty(message = "短信签名不能为空")
-    private String signature;
-    /**
-     * 渠道编码
-     *
-     * 枚举 {@link SmsChannelEnum}
-     */
-    @NotEmpty(message = "渠道编码不能为空")
-    private String code;
-    /**
-     * 短信 API 的账号
-     */
-    @NotEmpty(message = "短信 API 的账号不能为空")
-    private String apiKey;
-    /**
-     * 短信 API 的密钥
-     */
-    @NotEmpty(message = "短信 API 的密钥不能为空")
-    private String apiSecret;
-    /**
-     * 短信发送回调 URL
-     */
-    private String callbackUrl;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/mq/consumer/sms/SmsSendConsumer.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/mq/consumer/sms/SmsSendConsumer.java
deleted file mode 100644
index 0987c87..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/mq/consumer/sms/SmsSendConsumer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.iailab.module.system.mq.consumer.sms;
-
-import com.iailab.module.system.mq.message.sms.SmsSendMessage;
-import com.iailab.module.system.service.sms.SmsSendService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.event.EventListener;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * 针对 {@link SmsSendMessage} 的消费者
- *
- * @author zzf
- */
-@Component
-@Slf4j
-public class SmsSendConsumer {
-
-    @Resource
-    private SmsSendService smsSendService;
-
-    @EventListener
-    @Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
-    public void onMessage(SmsSendMessage message) {
-        log.info("[onMessage][消息内容({})]", message);
-        smsSendService.doSendSms(message);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthService.java
index 6699da4..dbf21eb 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthService.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthService.java
@@ -48,29 +48,6 @@
     void logout(String token, Integer logType);
 
     /**
-     * 短信验证码发送
-     *
-     * @param reqVO 发送请求
-     */
-    void sendSmsCode(AuthSmsSendReqVO reqVO);
-
-    /**
-     * 短信登录
-     *
-     * @param reqVO 登录信息
-     * @return 登录结果
-     */
-    AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO) ;
-
-    /**
-     * 社交快捷登录,使用 code 授权码
-     *
-     * @param reqVO 登录信息
-     * @return 登录结果
-     */
-    AuthLoginRespVO socialLogin(@Valid AuthSocialLoginReqVO reqVO);
-
-    /**
      * 刷新访问令牌
      *
      * @param refreshToken 刷新令牌
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthServiceImpl.java
index 1fa800b..115ad3e 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthServiceImpl.java
+++ b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/auth/AdminAuthServiceImpl.java
@@ -7,9 +7,6 @@
 import com.iailab.framework.common.util.servlet.ServletUtils;
 import com.iailab.framework.common.util.validation.ValidationUtils;
 import com.iailab.module.system.api.logger.dto.LoginLogCreateReqDTO;
-import com.iailab.module.system.api.sms.SmsCodeApi;
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
 import com.iailab.module.system.controller.admin.auth.vo.*;
 import com.iailab.module.system.convert.auth.AuthConvert;
 import com.iailab.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
@@ -21,7 +18,6 @@
 import com.iailab.module.system.service.logger.LoginLogService;
 import com.iailab.module.system.service.member.MemberService;
 import com.iailab.module.system.service.oauth2.OAuth2TokenService;
-import com.iailab.module.system.service.social.SocialUserService;
 import com.iailab.module.system.service.user.AdminUserService;
 import com.google.common.annotations.VisibleForTesting;
 import com.xingyuv.captcha.model.common.ResponseModel;
@@ -36,7 +32,6 @@
 import java.util.Objects;
 
 import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.framework.common.util.servlet.ServletUtils.getClientIP;
 import static com.iailab.module.system.enums.ErrorCodeConstants.*;
 
 /**
@@ -55,15 +50,11 @@
     @Resource
     private OAuth2TokenService oauth2TokenService;
     @Resource
-    private SocialUserService socialUserService;
-    @Resource
     private MemberService memberService;
     @Resource
     private Validator validator;
     @Resource
     private CaptchaService captchaService;
-    @Resource
-    private SmsCodeApi smsCodeApi;
 
     /**
      * 验证码的开关,默认为 true
@@ -106,38 +97,8 @@
         // 使用账号密码,进行登录
         AdminUserDO user = authenticate(reqVO.getUsername(), reqVO.getPassword());
 
-        // 如果 socialType 非空,说明需要绑定社交用户
-        if (reqVO.getSocialType() != null) {
-            socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
-                    reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
-        }
         // 创建 Token 令牌,记录登录日志
         return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
-    }
-
-    @Override
-    public void sendSmsCode(AuthSmsSendReqVO reqVO) {
-        // 登录场景,验证是否存在
-        if (userService.getUserByMobile(reqVO.getMobile()) == null) {
-            throw exception(AUTH_MOBILE_NOT_EXISTS);
-        }
-        // 发送验证码
-        smsCodeApi.sendSmsCode(AuthConvert.INSTANCE.convert(reqVO).setCreateIp(getClientIP()));
-    }
-
-    @Override
-    public AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO) {
-        // 校验验证码
-        smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), getClientIP())).getCheckedData();
-
-        // 获得用户信息
-        AdminUserDO user = userService.getUserByMobile(reqVO.getMobile());
-        if (user == null) {
-            throw exception(USER_NOT_EXISTS);
-        }
-
-        // 创建 Token 令牌,记录登录日志
-        return createTokenAfterLoginSuccess(user.getId(), reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE);
     }
 
     private void createLoginLog(Long userId, String username,
@@ -157,25 +118,6 @@
         if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
             userService.updateUserLogin(userId, ServletUtils.getClientIP());
         }
-    }
-
-    @Override
-    public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) {
-        // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
-        SocialUserRespDTO socialUser = socialUserService.getSocialUserByCode(UserTypeEnum.ADMIN.getValue(), reqVO.getType(),
-                reqVO.getCode(), reqVO.getState());
-        if (socialUser == null || socialUser.getUserId() == null) {
-            throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
-        }
-
-        // 获得用户
-        AdminUserDO user = userService.getUser(socialUser.getUserId());
-        if (user == null) {
-            throw exception(USER_NOT_EXISTS);
-        }
-
-        // 创建 Token 令牌,记录登录日志
-        return createTokenAfterLoginSuccess(user.getId(), user.getUsername(), LoginLogTypeEnum.LOGIN_SOCIAL);
     }
 
     @VisibleForTesting
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsChannelService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsChannelService.java
deleted file mode 100644
index 047e0ac..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsChannelService.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-
-import javax.validation.Valid;
-import java.util.List;
-
-/**
- * 短信渠道 Service 接口
- *
- * @author zzf
- * @since 2021/1/25 9:24
- */
-public interface SmsChannelService {
-
-    /**
-     * 创建短信渠道
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Long createSmsChannel(@Valid SmsChannelSaveReqVO createReqVO);
-
-    /**
-     * 更新短信渠道
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateSmsChannel(@Valid SmsChannelSaveReqVO updateReqVO);
-
-    /**
-     * 删除短信渠道
-     *
-     * @param id 编号
-     */
-    void deleteSmsChannel(Long id);
-
-    /**
-     * 获得短信渠道
-     *
-     * @param id 编号
-     * @return 短信渠道
-     */
-    SmsChannelDO getSmsChannel(Long id);
-
-    /**
-     * 获得所有短信渠道列表
-     *
-     * @return 短信渠道列表
-     */
-    List<SmsChannelDO> getSmsChannelList();
-
-    /**
-     * 获得短信渠道分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 短信渠道分页
-     */
-    PageResult<SmsChannelDO> getSmsChannelPage(SmsChannelPageReqVO pageReqVO);
-
-    /**
-     * 获得短信客户端
-     *
-     * @param id 编号
-     * @return 短信客户端
-     */
-    SmsClient getSmsClient(Long id);
-
-    /**
-     * 获得短信客户端
-     *
-     * @param code 编码
-     * @return 短信客户端
-     */
-    SmsClient getSmsClient(String code);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsChannelServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsChannelServiceImpl.java
deleted file mode 100644
index 1e9db0a..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsChannelServiceImpl.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.SmsClientFactory;
-import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.dal.mysql.sms.SmsChannelMapper;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.time.Duration;
-import java.util.List;
-
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
-import static com.iailab.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
-import static com.iailab.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
-
-/**
- * 短信渠道 Service 实现类
- *
- * @author zzf
- */
-@Service
-@Slf4j
-public class SmsChannelServiceImpl implements SmsChannelService {
-
-    /**
-     * {@link SmsClient} 缓存,通过它异步刷新 smsClientFactory
-     */
-    @Getter
-    private final LoadingCache<Long, SmsClient> idClientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
-            new CacheLoader<Long, SmsClient>() {
-
-                @Override
-                public SmsClient load(Long id) {
-                    // 查询,然后尝试刷新
-                    SmsChannelDO channel = smsChannelMapper.selectById(id);
-                    if (channel != null) {
-                        SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class);
-                        smsClientFactory.createOrUpdateSmsClient(properties);
-                    }
-                    return smsClientFactory.getSmsClient(id);
-                }
-
-            });
-
-    /**
-     * {@link SmsClient} 缓存,通过它异步刷新 smsClientFactory
-     */
-    @Getter
-    private final LoadingCache<String, SmsClient> codeClientCache = buildAsyncReloadingCache(Duration.ofSeconds(60L),
-            new CacheLoader<String, SmsClient>() {
-
-                @Override
-                public SmsClient load(String code) {
-                    // 查询,然后尝试刷新
-                    SmsChannelDO channel = smsChannelMapper.selectByCode(code);
-                    if (channel != null) {
-                        SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class);
-                        smsClientFactory.createOrUpdateSmsClient(properties);
-                    }
-                    return smsClientFactory.getSmsClient(code);
-                }
-
-            });
-
-    @Resource
-    private SmsClientFactory smsClientFactory;
-
-    @Resource
-    private SmsChannelMapper smsChannelMapper;
-
-    @Resource
-    private SmsTemplateService smsTemplateService;
-
-    @Override
-    public Long createSmsChannel(SmsChannelSaveReqVO createReqVO) {
-        SmsChannelDO channel = BeanUtils.toBean(createReqVO, SmsChannelDO.class);
-        smsChannelMapper.insert(channel);
-        return channel.getId();
-    }
-
-    @Override
-    public void updateSmsChannel(SmsChannelSaveReqVO updateReqVO) {
-        // 校验存在
-        SmsChannelDO channel = validateSmsChannelExists(updateReqVO.getId());
-        // 更新
-        SmsChannelDO updateObj = BeanUtils.toBean(updateReqVO, SmsChannelDO.class);
-        smsChannelMapper.updateById(updateObj);
-
-        // 清空缓存
-        clearCache(updateReqVO.getId(), channel.getCode());
-    }
-
-    @Override
-    public void deleteSmsChannel(Long id) {
-        // 校验存在
-        SmsChannelDO channel = validateSmsChannelExists(id);
-        // 校验是否有在使用该账号的模版
-        if (smsTemplateService.getSmsTemplateCountByChannelId(id) > 0) {
-            throw exception(SMS_CHANNEL_HAS_CHILDREN);
-        }
-        // 删除
-        smsChannelMapper.deleteById(id);
-
-        // 清空缓存
-        clearCache(id, channel.getCode());
-    }
-
-    /**
-     * 清空指定渠道编号的缓存
-     *
-     * @param id 渠道编号
-     * @param code 渠道编码
-     */
-    private void clearCache(Long id, String code) {
-        idClientCache.invalidate(id);
-        if (StrUtil.isNotEmpty(code)) {
-            codeClientCache.invalidate(code);
-        }
-    }
-
-    private SmsChannelDO validateSmsChannelExists(Long id) {
-        SmsChannelDO channel = smsChannelMapper.selectById(id);
-        if (channel == null) {
-            throw exception(SMS_CHANNEL_NOT_EXISTS);
-        }
-        return channel;
-    }
-
-    @Override
-    public SmsChannelDO getSmsChannel(Long id) {
-        return smsChannelMapper.selectById(id);
-    }
-
-    @Override
-    public List<SmsChannelDO> getSmsChannelList() {
-        return smsChannelMapper.selectList();
-    }
-
-    @Override
-    public PageResult<SmsChannelDO> getSmsChannelPage(SmsChannelPageReqVO pageReqVO) {
-        return smsChannelMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public SmsClient getSmsClient(Long id) {
-        return idClientCache.getUnchecked(id);
-    }
-
-    @Override
-    public SmsClient getSmsClient(String code) {
-        return codeClientCache.getUnchecked(code);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsCodeService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsCodeService.java
deleted file mode 100644
index ce5ae1e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsCodeService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
-
-import javax.validation.Valid;
-
-/**
- * 短信验证码 Service 接口
- *
- * @author iailab
- */
-public interface SmsCodeService {
-
-    /**
-     * 创建短信验证码,并进行发送
-     *
-     * @param reqDTO 发送请求
-     */
-    void sendSmsCode(@Valid SmsCodeSendReqDTO reqDTO);
-
-    /**
-     * 验证短信验证码,并进行使用
-     * 如果正确,则将验证码标记成已使用
-     * 如果错误,则抛出 {@link ServiceException} 异常
-     *
-     * @param reqDTO 使用请求
-     */
-    void useSmsCode(@Valid SmsCodeUseReqDTO reqDTO);
-
-    /**
-     * 检查验证码是否有效
-     *
-     * @param reqDTO 校验请求
-     */
-    void validateSmsCode(@Valid SmsCodeValidateReqDTO reqDTO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsCodeServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsCodeServiceImpl.java
deleted file mode 100644
index d7dd35e..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsCodeServiceImpl.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.map.MapUtil;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
-import com.iailab.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
-import com.iailab.module.system.dal.dataobject.sms.SmsCodeDO;
-import com.iailab.module.system.dal.mysql.sms.SmsCodeMapper;
-import com.iailab.module.system.enums.sms.SmsSceneEnum;
-import com.iailab.module.system.framework.sms.config.SmsCodeProperties;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-
-import static cn.hutool.core.util.RandomUtil.randomInt;
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.framework.common.util.date.DateUtils.isToday;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-
-/**
- * 短信验证码 Service 实现类
- *
- * @author iailab
- */
-@Service
-@Validated
-public class SmsCodeServiceImpl implements SmsCodeService {
-
-    @Resource
-    private SmsCodeProperties smsCodeProperties;
-
-    @Resource
-    private SmsCodeMapper smsCodeMapper;
-
-    @Resource
-    private SmsSendService smsSendService;
-
-    @Override
-    public void sendSmsCode(SmsCodeSendReqDTO reqDTO) {
-        SmsSceneEnum sceneEnum = SmsSceneEnum.getCodeByScene(reqDTO.getScene());
-        Assert.notNull(sceneEnum, "验证码场景({}) 查找不到配置", reqDTO.getScene());
-        // 创建验证码
-        String code = createSmsCode(reqDTO.getMobile(), reqDTO.getScene(), reqDTO.getCreateIp());
-        // 发送验证码
-        smsSendService.sendSingleSms(reqDTO.getMobile(), null, null,
-                sceneEnum.getTemplateCode(), MapUtil.of("code", code));
-    }
-
-    private String createSmsCode(String mobile, Integer scene, String ip) {
-        // 校验是否可以发送验证码,不用筛选场景
-        SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null, null);
-        if (lastSmsCode != null) {
-            if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis()
-                    < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁
-                throw exception(SMS_CODE_SEND_TOO_FAST);
-            }
-            if (isToday(lastSmsCode.getCreateTime()) && // 必须是今天,才能计算超过当天的上限
-                    lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。
-                throw exception(SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);
-            }
-            // TODO iailab:提升,每个 IP 每天可发送数量
-            // TODO iailab:提升,每个 IP 每小时可发送数量
-        }
-
-        // 创建验证码记录
-        String code = String.format("%0" + smsCodeProperties.getEndCode().toString().length() + "d",
-                randomInt(smsCodeProperties.getBeginCode(), smsCodeProperties.getEndCode() + 1));
-        SmsCodeDO newSmsCode = SmsCodeDO.builder().mobile(mobile).code(code).scene(scene)
-                .todayIndex(lastSmsCode != null && isToday(lastSmsCode.getCreateTime()) ? lastSmsCode.getTodayIndex() + 1 : 1)
-                .createIp(ip).used(false).build();
-        smsCodeMapper.insert(newSmsCode);
-        return code;
-    }
-
-    @Override
-    public void useSmsCode(SmsCodeUseReqDTO reqDTO) {
-        // 检测验证码是否有效
-        SmsCodeDO lastSmsCode = validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene());
-        // 使用验证码
-        smsCodeMapper.updateById(SmsCodeDO.builder().id(lastSmsCode.getId())
-                .used(true).usedTime(LocalDateTime.now()).usedIp(reqDTO.getUsedIp()).build());
-    }
-
-    @Override
-    public void validateSmsCode(SmsCodeValidateReqDTO reqDTO) {
-        validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene());
-    }
-
-    private SmsCodeDO validateSmsCode0(String mobile, String code, Integer scene) {
-        // 校验验证码
-        SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, code, scene);
-        // 若验证码不存在,抛出异常
-        if (lastSmsCode == null) {
-            throw exception(SMS_CODE_NOT_FOUND);
-        }
-        // 超过时间
-        if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis()
-                >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
-            throw exception(SMS_CODE_EXPIRED);
-        }
-        // 判断验证码是否已被使用
-        if (Boolean.TRUE.equals(lastSmsCode.getUsed())) {
-            throw exception(SMS_CODE_USED);
-        }
-        return lastSmsCode;
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsLogService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsLogService.java
deleted file mode 100644
index 55f81f8..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsLogService.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsLogDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-
-import java.time.LocalDateTime;
-import java.util.Map;
-
-/**
- * 短信日志 Service 接口
- *
- * @author zzf
- * @date 13:48 2021/3/2
- */
-public interface SmsLogService {
-
-    /**
-     * 创建短信日志
-     *
-     * @param mobile 手机号
-     * @param userId 用户编号
-     * @param userType 用户类型
-     * @param isSend 是否发送
-     * @param template 短信模板
-     * @param templateContent 短信内容
-     * @param templateParams 短信参数
-     * @return 发送日志编号
-     */
-    Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend,
-                      SmsTemplateDO template, String templateContent, Map<String, Object> templateParams);
-
-    /**
-     * 更新日志的发送结果
-     *
-     * @param id 日志编号
-     * @param success 发送是否成功
-     * @param apiSendCode 短信 API 发送结果的编码
-     * @param apiSendMsg 短信 API 发送失败的提示
-     * @param apiRequestId 短信 API 发送返回的唯一请求 ID
-     * @param apiSerialNo 短信 API 发送返回的序号
-     */
-    void updateSmsSendResult(Long id, Boolean success,
-                             String apiSendCode, String apiSendMsg,
-                             String apiRequestId, String apiSerialNo);
-
-    /**
-     * 更新日志的接收结果
-     *
-     * @param id 日志编号
-     * @param success 是否接收成功
-     * @param receiveTime 用户接收时间
-     * @param apiReceiveCode API 接收结果的编码
-     * @param apiReceiveMsg API 接收结果的说明
-     */
-    void updateSmsReceiveResult(Long id, Boolean success,
-                                LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg);
-
-    /**
-     * 获得短信日志分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 短信日志分页
-     */
-    PageResult<SmsLogDO> getSmsLogPage(SmsLogPageReqVO pageReqVO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsLogServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsLogServiceImpl.java
deleted file mode 100644
index 268a4d0..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsLogServiceImpl.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsLogDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.dal.mysql.sms.SmsLogMapper;
-import com.iailab.module.system.enums.sms.SmsReceiveStatusEnum;
-import com.iailab.module.system.enums.sms.SmsSendStatusEnum;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.time.LocalDateTime;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * 短信日志 Service 实现类
- *
- * @author zzf
- */
-@Slf4j
-@Service
-public class SmsLogServiceImpl implements SmsLogService {
-
-    @Resource
-    private SmsLogMapper smsLogMapper;
-
-    @Override
-    public Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend,
-                             SmsTemplateDO template, String templateContent, Map<String, Object> templateParams) {
-        SmsLogDO.SmsLogDOBuilder logBuilder = SmsLogDO.builder();
-        // 根据是否要发送,设置状态
-        logBuilder.sendStatus(Objects.equals(isSend, true) ? SmsSendStatusEnum.INIT.getStatus()
-                : SmsSendStatusEnum.IGNORE.getStatus());
-        // 设置手机相关字段
-        logBuilder.mobile(mobile).userId(userId).userType(userType);
-        // 设置模板相关字段
-        logBuilder.templateId(template.getId()).templateCode(template.getCode()).templateType(template.getType());
-        logBuilder.templateContent(templateContent).templateParams(templateParams)
-                .apiTemplateId(template.getApiTemplateId());
-        // 设置渠道相关字段
-        logBuilder.channelId(template.getChannelId()).channelCode(template.getChannelCode());
-        // 设置接收相关字段
-        logBuilder.receiveStatus(SmsReceiveStatusEnum.INIT.getStatus());
-
-        // 插入数据库
-        SmsLogDO logDO = logBuilder.build();
-        smsLogMapper.insert(logDO);
-        return logDO.getId();
-    }
-
-    @Override
-    public void updateSmsSendResult(Long id, Boolean success,
-                                    String apiSendCode, String apiSendMsg,
-                                    String apiRequestId, String apiSerialNo) {
-        SmsSendStatusEnum sendStatus = success ? SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE;
-        smsLogMapper.updateById(SmsLogDO.builder().id(id)
-                .sendStatus(sendStatus.getStatus()).sendTime(LocalDateTime.now())
-                .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg)
-                .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build());
-    }
-
-    @Override
-    public void updateSmsReceiveResult(Long id, Boolean success, LocalDateTime receiveTime,
-                                       String apiReceiveCode, String apiReceiveMsg) {
-        SmsReceiveStatusEnum receiveStatus = Objects.equals(success, true) ?
-                SmsReceiveStatusEnum.SUCCESS : SmsReceiveStatusEnum.FAILURE;
-        smsLogMapper.updateById(SmsLogDO.builder().id(id).receiveStatus(receiveStatus.getStatus())
-                .receiveTime(receiveTime).apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build());
-    }
-
-    @Override
-    public PageResult<SmsLogDO> getSmsLogPage(SmsLogPageReqVO pageReqVO) {
-        return smsLogMapper.selectPage(pageReqVO);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsSendService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsSendService.java
deleted file mode 100644
index db29516..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsSendService.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.module.system.mq.message.sms.SmsSendMessage;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 短信发送 Service 接口
- *
- * @author iailab
- */
-public interface SmsSendService {
-
-    /**
-     * 发送单条短信给管理后台的用户
-     *
-     * 在 mobile 为空时,使用 userId 加载对应管理员的手机号
-     *
-     * @param mobile 手机号
-     * @param userId 用户编号
-     * @param templateCode 短信模板编号
-     * @param templateParams 短信模板参数
-     * @return 发送日志编号
-     */
-    Long sendSingleSmsToAdmin(String mobile, Long userId,
-                              String templateCode, Map<String, Object> templateParams);
-
-    /**
-     * 发送单条短信给用户 APP 的用户
-     *
-     * 在 mobile 为空时,使用 userId 加载对应会员的手机号
-     *
-     * @param mobile 手机号
-     * @param userId 用户编号
-     * @param templateCode 短信模板编号
-     * @param templateParams 短信模板参数
-     * @return 发送日志编号
-     */
-    Long sendSingleSmsToMember(String mobile, Long userId,
-                               String templateCode, Map<String, Object> templateParams);
-
-    /**
-     * 发送单条短信给用户
-     *
-     * @param mobile 手机号
-     * @param userId 用户编号
-     * @param userType 用户类型
-     * @param templateCode 短信模板编号
-     * @param templateParams 短信模板参数
-     * @return 发送日志编号
-     */
-    Long sendSingleSms(String mobile, Long userId, Integer userType,
-                       String templateCode, Map<String, Object> templateParams);
-
-    default void sendBatchSms(List<String> mobiles, List<Long> userIds, Integer userType,
-                              String templateCode, Map<String, Object> templateParams) {
-        throw new UnsupportedOperationException("暂时不支持该操作,感兴趣可以实现该功能哟!");
-    }
-
-    /**
-     * 执行真正的短信发送
-     * 注意,该方法仅仅提供给 MQ Consumer 使用
-     *
-     * @param message 短信
-     */
-    void doSendSms(SmsSendMessage message);
-
-    /**
-     * 接收短信的接收结果
-     *
-     * @param channelCode 渠道编码
-     * @param text 结果内容
-     * @throws Throwable 处理失败时,抛出异常
-     */
-    void receiveSmsStatus(String channelCode, String text) throws Throwable;
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsSendServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsSendServiceImpl.java
deleted file mode 100644
index aeb0f14..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsSendServiceImpl.java
+++ /dev/null
@@ -1,191 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.core.KeyValue;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.enums.UserTypeEnum;
-import com.iailab.framework.datapermission.core.annotation.DataPermission;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
-import com.iailab.module.system.mq.message.sms.SmsSendMessage;
-import com.iailab.module.system.mq.producer.sms.SmsProducer;
-import com.iailab.module.system.service.member.MemberService;
-import com.iailab.module.system.service.user.AdminUserService;
-import com.google.common.annotations.VisibleForTesting;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-
-/**
- * 短信发送 Service 发送的实现
- *
- * @author iailab
- */
-@Service
-@Slf4j
-public class SmsSendServiceImpl implements SmsSendService {
-
-    @Resource
-    private AdminUserService adminUserService;
-    @Resource
-    private MemberService memberService;
-    @Resource
-    private SmsChannelService smsChannelService;
-    @Resource
-    private SmsTemplateService smsTemplateService;
-    @Resource
-    private SmsLogService smsLogService;
-
-    @Resource
-    private SmsProducer smsProducer;
-
-    @Override
-    @DataPermission(enable = false) // 发送短信时,无需考虑数据权限
-    public Long sendSingleSmsToAdmin(String mobile, Long userId, String templateCode, Map<String, Object> templateParams) {
-        // 如果 mobile 为空,则加载用户编号对应的手机号
-        if (StrUtil.isEmpty(mobile)) {
-            AdminUserDO user = adminUserService.getUser(userId);
-            if (user != null) {
-                mobile = user.getMobile();
-            }
-        }
-        // 执行发送
-        return sendSingleSms(mobile, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams);
-    }
-
-    @Override
-    public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map<String, Object> templateParams) {
-        // 如果 mobile 为空,则加载用户编号对应的手机号
-        if (StrUtil.isEmpty(mobile)) {
-            mobile = memberService.getMemberUserMobile(userId);
-        }
-        // 执行发送
-        return sendSingleSms(mobile, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams);
-    }
-
-    @Override
-    public Long sendSingleSms(String mobile, Long userId, Integer userType,
-                              String templateCode, Map<String, Object> templateParams) {
-        // 校验短信模板是否合法
-        SmsTemplateDO template = validateSmsTemplate(templateCode);
-        // 校验短信渠道是否合法
-        SmsChannelDO smsChannel = validateSmsChannel(template.getChannelId());
-
-        // 校验手机号码是否存在
-        mobile = validateMobile(mobile);
-        // 构建有序的模板参数。为什么放在这个位置,是提前保证模板参数的正确性,而不是到了插入发送日志
-        List<KeyValue<String, Object>> newTemplateParams = buildTemplateParams(template, templateParams);
-
-        // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志
-        Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus())
-                && CommonStatusEnum.ENABLE.getStatus().equals(smsChannel.getStatus());
-        String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams);
-        Long sendLogId = smsLogService.createSmsLog(mobile, userId, userType, isSend, template, content, templateParams);
-
-        // 发送 MQ 消息,异步执行发送短信
-        if (isSend) {
-            smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(),
-                    template.getApiTemplateId(), newTemplateParams);
-        }
-        return sendLogId;
-    }
-
-    @VisibleForTesting
-    SmsChannelDO validateSmsChannel(Long channelId) {
-        // 获得短信模板。考虑到效率,从缓存中获取
-        SmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId);
-        // 短信模板不存在
-        if (channelDO == null) {
-            throw exception(SMS_CHANNEL_NOT_EXISTS);
-        }
-        return channelDO;
-    }
-
-    @VisibleForTesting
-    SmsTemplateDO validateSmsTemplate(String templateCode) {
-        // 获得短信模板。考虑到效率,从缓存中获取
-        SmsTemplateDO template = smsTemplateService.getSmsTemplateByCodeFromCache(templateCode);
-        // 短信模板不存在
-        if (template == null) {
-            throw exception(SMS_SEND_TEMPLATE_NOT_EXISTS);
-        }
-        return template;
-    }
-
-    /**
-     * 将参数模板,处理成有序的 KeyValue 数组
-     * <p>
-     * 原因是,部分短信平台并不是使用 key 作为参数,而是数组下标,例如说 <a href="https://cloud.tencent.com/document/product/382/39023">腾讯云</a>
-     *
-     * @param template       短信模板
-     * @param templateParams 原始参数
-     * @return 处理后的参数
-     */
-    @VisibleForTesting
-    List<KeyValue<String, Object>> buildTemplateParams(SmsTemplateDO template, Map<String, Object> templateParams) {
-        return template.getParams().stream().map(key -> {
-            Object value = templateParams.get(key);
-            if (value == null) {
-                throw exception(SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS, key);
-            }
-            return new KeyValue<>(key, value);
-        }).collect(Collectors.toList());
-    }
-
-    @VisibleForTesting
-    public String validateMobile(String mobile) {
-        if (StrUtil.isEmpty(mobile)) {
-            throw exception(SMS_SEND_MOBILE_NOT_EXISTS);
-        }
-        return mobile;
-    }
-
-    @Override
-    public void doSendSms(SmsSendMessage message) {
-        // 获得渠道对应的 SmsClient 客户端
-        SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId());
-        Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId());
-        // 发送短信
-        try {
-            SmsSendRespDTO sendResponse = smsClient.sendSms(message.getLogId(), message.getMobile(),
-                    message.getApiTemplateId(), message.getTemplateParams());
-            smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(),
-                    sendResponse.getApiCode(), sendResponse.getApiMsg(),
-                    sendResponse.getApiRequestId(), sendResponse.getSerialNo());
-        } catch (Throwable ex) {
-            log.error("[doSendSms][发送短信异常,日志编号({})]", message.getLogId(), ex);
-            smsLogService.updateSmsSendResult(message.getLogId(), false,
-                    "EXCEPTION", ExceptionUtil.getRootCauseMessage(ex), null, null);
-        }
-    }
-
-    @Override
-    public void receiveSmsStatus(String channelCode, String text) throws Throwable {
-        // 获得渠道对应的 SmsClient 客户端
-        SmsClient smsClient = smsChannelService.getSmsClient(channelCode);
-        Assert.notNull(smsClient, "短信客户端({}) 不存在", channelCode);
-        // 解析内容
-        List<SmsReceiveRespDTO> receiveResults = smsClient.parseSmsReceiveStatus(text);
-        if (CollUtil.isEmpty(receiveResults)) {
-            return;
-        }
-        // 更新短信日志的接收结果. 因为量一般不大,所以先使用 for 循环更新
-        receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(result.getLogId(),
-                result.getSuccess(), result.getReceiveTime(), result.getErrorCode(), result.getErrorMsg()));
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsTemplateService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsTemplateService.java
deleted file mode 100644
index 9179dc1..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsTemplateService.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-
-import javax.validation.Valid;
-import java.util.Map;
-
-/**
- * 短信模板 Service 接口
- *
- * @author zzf
- * @since 2021/1/25 9:24
- */
-public interface SmsTemplateService {
-
-    /**
-     * 创建短信模板
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Long createSmsTemplate(@Valid SmsTemplateSaveReqVO createReqVO);
-
-    /**
-     * 更新短信模板
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateSmsTemplate(@Valid SmsTemplateSaveReqVO updateReqVO);
-
-    /**
-     * 删除短信模板
-     *
-     * @param id 编号
-     */
-    void deleteSmsTemplate(Long id);
-
-    /**
-     * 获得短信模板
-     *
-     * @param id 编号
-     * @return 短信模板
-     */
-    SmsTemplateDO getSmsTemplate(Long id);
-
-    /**
-     * 获得短信模板,从缓存中
-     *
-     * @param code 模板编码
-     * @return 短信模板
-     */
-    SmsTemplateDO getSmsTemplateByCodeFromCache(String code);
-
-    /**
-     * 获得短信模板分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 短信模板分页
-     */
-    PageResult<SmsTemplateDO> getSmsTemplatePage(SmsTemplatePageReqVO pageReqVO);
-
-    /**
-     * 获得指定短信渠道下的短信模板数量
-     *
-     * @param channelId 短信渠道编号
-     * @return 数量
-     */
-    Long getSmsTemplateCountByChannelId(Long channelId);
-
-    /**
-     * 格式化短信内容
-     *
-     * @param content 短信模板的内容
-     * @param params 内容的参数
-     * @return 格式化后的内容
-     */
-    String formatSmsTemplateContent(String content, Map<String, Object> params);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsTemplateServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsTemplateServiceImpl.java
deleted file mode 100644
index 8297cee..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/sms/SmsTemplateServiceImpl.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.iailab.module.system.service.sms;
-
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.ReUtil;
-import cn.hutool.core.util.StrUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.framework.sms.core.client.SmsClient;
-import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
-import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
-import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
-import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
-import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
-import com.iailab.module.system.dal.mysql.sms.SmsTemplateMapper;
-import com.iailab.module.system.dal.redis.RedisKeyConstants;
-import com.google.common.annotations.VisibleForTesting;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-
-/**
- * 短信模板 Service 实现类
- *
- * @author zzf
- * @since 2021/1/25 9:25
- */
-@Service
-@Slf4j
-public class SmsTemplateServiceImpl implements SmsTemplateService {
-
-    /**
-     * 正则表达式,匹配 {} 中的变量
-     */
-    private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}");
-
-    @Resource
-    private SmsTemplateMapper smsTemplateMapper;
-
-    @Resource
-    private SmsChannelService smsChannelService;
-
-    @Override
-    public Long createSmsTemplate(SmsTemplateSaveReqVO createReqVO) {
-        // 校验短信渠道
-        SmsChannelDO channelDO = validateSmsChannel(createReqVO.getChannelId());
-        // 校验短信编码是否重复
-        validateSmsTemplateCodeDuplicate(null, createReqVO.getCode());
-        // 校验短信模板
-        validateApiTemplate(createReqVO.getChannelId(), createReqVO.getApiTemplateId());
-
-        // 插入
-        SmsTemplateDO template = BeanUtils.toBean(createReqVO, SmsTemplateDO.class);
-        template.setParams(parseTemplateContentParams(template.getContent()));
-        template.setChannelCode(channelDO.getCode());
-        smsTemplateMapper.insert(template);
-        // 返回
-        return template.getId();
-    }
-
-    @Override
-    @CacheEvict(cacheNames = RedisKeyConstants.SMS_TEMPLATE,
-            allEntries = true) // allEntries 清空所有缓存,因为可能修改到 code 字段,不好清理
-    public void updateSmsTemplate(SmsTemplateSaveReqVO updateReqVO) {
-        // 校验存在
-        validateSmsTemplateExists(updateReqVO.getId());
-        // 校验短信渠道
-        SmsChannelDO channelDO = validateSmsChannel(updateReqVO.getChannelId());
-        // 校验短信编码是否重复
-        validateSmsTemplateCodeDuplicate(updateReqVO.getId(), updateReqVO.getCode());
-        // 校验短信模板
-        validateApiTemplate(updateReqVO.getChannelId(), updateReqVO.getApiTemplateId());
-
-        // 更新
-        SmsTemplateDO updateObj = BeanUtils.toBean(updateReqVO, SmsTemplateDO.class);
-        updateObj.setParams(parseTemplateContentParams(updateObj.getContent()));
-        updateObj.setChannelCode(channelDO.getCode());
-        smsTemplateMapper.updateById(updateObj);
-    }
-
-    @Override
-    @CacheEvict(cacheNames = RedisKeyConstants.SMS_TEMPLATE,
-            allEntries = true) // allEntries 清空所有缓存,因为 id 不是直接的缓存 code,不好清理
-    public void deleteSmsTemplate(Long id) {
-        // 校验存在
-        validateSmsTemplateExists(id);
-        // 更新
-        smsTemplateMapper.deleteById(id);
-    }
-
-    private void validateSmsTemplateExists(Long id) {
-        if (smsTemplateMapper.selectById(id) == null) {
-            throw exception(SMS_TEMPLATE_NOT_EXISTS);
-        }
-    }
-
-    @Override
-    public SmsTemplateDO getSmsTemplate(Long id) {
-        return smsTemplateMapper.selectById(id);
-    }
-
-    @Override
-    @Cacheable(cacheNames = RedisKeyConstants.SMS_TEMPLATE, key = "#code",
-            unless = "#result == null")
-    public SmsTemplateDO getSmsTemplateByCodeFromCache(String code) {
-        return smsTemplateMapper.selectByCode(code);
-    }
-
-    @Override
-    public PageResult<SmsTemplateDO> getSmsTemplatePage(SmsTemplatePageReqVO pageReqVO) {
-        return smsTemplateMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public Long getSmsTemplateCountByChannelId(Long channelId) {
-        return smsTemplateMapper.selectCountByChannelId(channelId);
-    }
-
-    @VisibleForTesting
-    public SmsChannelDO validateSmsChannel(Long channelId) {
-        SmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId);
-        if (channelDO == null) {
-            throw exception(SMS_CHANNEL_NOT_EXISTS);
-        }
-        if (CommonStatusEnum.isDisable(channelDO.getStatus())) {
-            throw exception(SMS_CHANNEL_DISABLE);
-        }
-        return channelDO;
-    }
-
-    @VisibleForTesting
-    public void validateSmsTemplateCodeDuplicate(Long id, String code) {
-        SmsTemplateDO template = smsTemplateMapper.selectByCode(code);
-        if (template == null) {
-            return;
-        }
-        // 如果 id 为空,说明不用比较是否为相同 id 的字典类型
-        if (id == null) {
-            throw exception(SMS_TEMPLATE_CODE_DUPLICATE, code);
-        }
-        if (!template.getId().equals(id)) {
-            throw exception(SMS_TEMPLATE_CODE_DUPLICATE, code);
-        }
-    }
-
-    /**
-     * 校验 API 短信平台的模板是否有效
-     *
-     * @param channelId 渠道编号
-     * @param apiTemplateId API 模板编号
-     */
-    @VisibleForTesting
-    void validateApiTemplate(Long channelId, String apiTemplateId) {
-        // 获得短信模板
-        SmsClient smsClient = smsChannelService.getSmsClient(channelId);
-        Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId));
-        SmsTemplateRespDTO template;
-        try {
-            template = smsClient.getSmsTemplate(apiTemplateId);
-        } catch (Throwable ex) {
-            throw exception(SMS_TEMPLATE_API_ERROR, ExceptionUtil.getRootCauseMessage(ex));
-        }
-        // 校验短信模版
-        if (template == null) {
-            throw exception(SMS_TEMPLATE_API_NOT_FOUND);
-        }
-        if (Objects.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.CHECKING.getStatus())) {
-            throw exception(SMS_TEMPLATE_API_AUDIT_CHECKING);
-        }
-        if (Objects.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.FAIL.getStatus())) {
-            throw exception(SMS_TEMPLATE_API_AUDIT_FAIL, template.getAuditReason());
-        }
-        Assert.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.SUCCESS.getStatus(),
-                String.format("短信模板(%s) 审核状态(%d) 不正确", apiTemplateId, template.getAuditStatus()));
-    }
-
-    @Override
-    public String formatSmsTemplateContent(String content, Map<String, Object> params) {
-        return StrUtil.format(content, params);
-    }
-
-    @VisibleForTesting
-    List<String> parseTemplateContentParams(String content) {
-        return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialClientService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialClientService.java
deleted file mode 100644
index 7fc5afc..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialClientService.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.iailab.module.system.service.social;
-
-import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialClientDO;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.xingyuv.jushauth.model.AuthUser;
-import me.chanjar.weixin.common.bean.WxJsapiSignature;
-
-import javax.validation.Valid;
-
-/**
- * 社交应用 Service 接口
- *
- * @author iailab
- */
-public interface SocialClientService {
-
-    /**
-     * 获得社交平台的授权 URL
-     *
-     * @param socialType 社交平台的类型 {@link SocialTypeEnum}
-     * @param userType 用户类型
-     * @param redirectUri 重定向 URL
-     * @return 社交平台的授权 URL
-     */
-    String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri);
-
-    /**
-     * 请求社交平台,获得授权的用户
-     *
-     * @param socialType 社交平台的类型
-     * @param userType 用户类型
-     * @param code 授权码
-     * @param state 授权 state
-     * @return 授权的用户
-     */
-    AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state);
-
-    // =================== 微信公众号独有 ===================
-
-    /**
-     * 创建微信公众号的 JS SDK 初始化所需的签名
-     *
-     * @param userType 用户类型
-     * @param url 访问的 URL 地址
-     * @return 签名
-     */
-    WxJsapiSignature createWxMpJsapiSignature(Integer userType, String url);
-
-    // =================== 微信小程序独有 ===================
-
-    /**
-     * 获得微信小程序的手机信息
-     *
-     * @param userType 用户类型
-     * @param phoneCode 手机授权码
-     * @return 手机信息
-     */
-    WxMaPhoneNumberInfo getWxMaPhoneNumberInfo(Integer userType, String phoneCode);
-
-    // =================== 客户端管理 ===================
-
-    /**
-     * 创建社交客户端
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Long createSocialClient(@Valid SocialClientSaveReqVO createReqVO);
-
-    /**
-     * 更新社交客户端
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateSocialClient(@Valid SocialClientSaveReqVO updateReqVO);
-
-    /**
-     * 删除社交客户端
-     *
-     * @param id 编号
-     */
-    void deleteSocialClient(Long id);
-
-    /**
-     * 获得社交客户端
-     *
-     * @param id 编号
-     * @return 社交客户端
-     */
-    SocialClientDO getSocialClient(Long id);
-
-    /**
-     * 获得社交客户端分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 社交客户端分页
-     */
-    PageResult<SocialClientDO> getSocialClientPage(SocialClientPageReqVO pageReqVO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialClientServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialClientServiceImpl.java
deleted file mode 100644
index c0a400f..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialClientServiceImpl.java
+++ /dev/null
@@ -1,351 +0,0 @@
-package com.iailab.module.system.service.social;
-
-import cn.binarywang.wx.miniapp.api.WxMaService;
-import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
-import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
-import cn.binarywang.wx.miniapp.config.impl.WxMaRedisBetterConfigImpl;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.ObjUtil;
-import cn.hutool.core.util.ReflectUtil;
-import com.iailab.framework.common.enums.CommonStatusEnum;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.framework.common.util.cache.CacheUtils;
-import com.iailab.framework.common.util.http.HttpUtils;
-import com.iailab.framework.common.util.object.BeanUtils;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
-import com.iailab.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialClientDO;
-import com.iailab.module.system.dal.mysql.social.SocialClientMapper;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
-import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.xingyuv.jushauth.config.AuthConfig;
-import com.xingyuv.jushauth.model.AuthCallback;
-import com.xingyuv.jushauth.model.AuthResponse;
-import com.xingyuv.jushauth.model.AuthUser;
-import com.xingyuv.jushauth.request.AuthRequest;
-import com.xingyuv.jushauth.utils.AuthStateUtils;
-import com.xingyuv.justauth.AuthRequestFactory;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import me.chanjar.weixin.common.bean.WxJsapiSignature;
-import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
-import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
-import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.time.Duration;
-import java.util.Objects;
-
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
-import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
-import static com.iailab.module.system.enums.ErrorCodeConstants.*;
-
-/**
- * 社交应用 Service 实现类
- *
- * @author iailab
- */
-@Service
-@Slf4j
-public class SocialClientServiceImpl implements SocialClientService {
-
-    /**
-     * 小程序版本
-     *
-     * 1. release:正式版
-     * 2. trial:体验版
-     * 3. developer:开发版
-     */
-    @Value("${yudao.wxa-code.env-version:release}")
-    public String envVersion;
-
-    @Resource
-    private AuthRequestFactory authRequestFactory;
-
-    @Resource
-    private WxMpService wxMpService;
-    @Resource
-    private WxMpProperties wxMpProperties;
-    @Resource
-    private StringRedisTemplate stringRedisTemplate; // WxMpService 需要使用到,所以在 Service 注入了它
-    /**
-     * 缓存 WxMpService 对象
-     *
-     * key:使用微信公众号的 appId + secret 拼接,即 {@link SocialClientDO} 的 clientId 和 clientSecret 属性。
-     * 为什么 key 使用这种格式?因为 {@link SocialClientDO} 在管理后台可以变更,通过这个 key 存储它的单例。
-     *
-     * 为什么要做 WxMpService 缓存?因为 WxMpService 构建成本比较大,所以尽量保证它是单例。
-     */
-    private final LoadingCache<String, WxMpService> wxMpServiceCache = buildAsyncReloadingCache(
-            Duration.ofSeconds(10L),
-            new CacheLoader<String, WxMpService>() {
-
-                @Override
-                public WxMpService load(String key) {
-                    String[] keys = key.split(":");
-                    return buildWxMpService(keys[0], keys[1]);
-                }
-
-            });
-
-    @Resource
-    private WxMaService wxMaService;
-    @Resource
-    private WxMaProperties wxMaProperties;
-    /**
-     * 缓存 WxMaService 对象
-     *
-     * 说明同 {@link #wxMpServiceCache} 变量
-     */
-    private final LoadingCache<String, WxMaService> wxMaServiceCache = buildAsyncReloadingCache(
-            Duration.ofSeconds(10L),
-            new CacheLoader<String, WxMaService>() {
-
-                @Override
-                public WxMaService load(String key) {
-                    String[] keys = key.split(":");
-                    return buildWxMaService(keys[0], keys[1]);
-                }
-
-            });
-
-    @Resource
-    private SocialClientMapper socialClientMapper;
-
-    @Override
-    public String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) {
-        // 获得对应的 AuthRequest 实现
-        AuthRequest authRequest = buildAuthRequest(socialType, userType);
-        // 生成跳转地址
-        String authorizeUri = authRequest.authorize(AuthStateUtils.createState());
-        return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);
-    }
-
-    @Override
-    public AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state) {
-        // 构建请求
-        AuthRequest authRequest = buildAuthRequest(socialType, userType);
-        AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build();
-        // 执行请求
-        AuthResponse<?> authResponse = authRequest.login(authCallback);
-        log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", socialType,
-                toJsonString(authCallback), toJsonString(authResponse));
-        if (!authResponse.ok()) {
-            throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg());
-        }
-        return (AuthUser) authResponse.getData();
-    }
-
-    /**
-     * 构建 AuthRequest 对象,支持多租户配置
-     *
-     * @param socialType 社交类型
-     * @param userType 用户类型
-     * @return AuthRequest 对象
-     */
-    @VisibleForTesting
-    AuthRequest buildAuthRequest(Integer socialType, Integer userType) {
-        // 1. 先查找默认的配置项,从 application-*.yaml 中读取
-        AuthRequest request = authRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource());
-        Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType));
-        // 2. 查询 DB 的配置项,如果存在则进行覆盖
-        SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(socialType, userType);
-        if (client != null && Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
-            // 2.1 构造新的 AuthConfig 对象
-            AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(request, "config");
-            AuthConfig newAuthConfig = ReflectUtil.newInstance(authConfig.getClass());
-            BeanUtil.copyProperties(authConfig, newAuthConfig);
-            // 2.2 修改对应的 clientId + clientSecret 密钥
-            newAuthConfig.setClientId(client.getClientId());
-            newAuthConfig.setClientSecret(client.getClientSecret());
-            if (client.getAgentId() != null) { // 如果有 agentId 则修改 agentId
-                newAuthConfig.setAgentId(client.getAgentId());
-            }
-            // 2.3 设置会 request 里,进行后续使用
-            ReflectUtil.setFieldValue(request, "config", newAuthConfig);
-        }
-        return request;
-    }
-
-    // =================== 微信公众号独有 ===================
-
-    @Override
-    @SneakyThrows
-    public WxJsapiSignature createWxMpJsapiSignature(Integer userType, String url) {
-        WxMpService service = getWxMpService(userType);
-        return service.createJsapiSignature(url);
-    }
-
-    /**
-     * 获得 clientId + clientSecret 对应的 WxMpService 对象
-     *
-     * @param userType 用户类型
-     * @return WxMpService 对象
-     */
-    @VisibleForTesting
-    WxMpService getWxMpService(Integer userType) {
-        // 第一步,查询 DB 的配置项,获得对应的 WxMpService 对象
-        SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
-                SocialTypeEnum.WECHAT_MP.getType(), userType);
-        if (client != null && Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
-            return wxMpServiceCache.getUnchecked(client.getClientId() + ":" + client.getClientSecret());
-        }
-        // 第二步,不存在 DB 配置项,则使用 application-*.yaml 对应的 WxMpService 对象
-        return wxMpService;
-    }
-
-    /**
-     * 创建 clientId + clientSecret 对应的 WxMpService 对象
-     *
-     * @param clientId 微信公众号 appId
-     * @param clientSecret 微信公众号 secret
-     * @return WxMpService 对象
-     */
-    public WxMpService buildWxMpService(String clientId, String clientSecret) {
-        // 第一步,创建 WxMpRedisConfigImpl 对象
-        WxMpRedisConfigImpl configStorage = new WxMpRedisConfigImpl(
-                new RedisTemplateWxRedisOps(stringRedisTemplate),
-                wxMpProperties.getConfigStorage().getKeyPrefix());
-        configStorage.setAppId(clientId);
-        configStorage.setSecret(clientSecret);
-
-        // 第二步,创建 WxMpService 对象
-        WxMpService service = new WxMpServiceImpl();
-        service.setWxMpConfigStorage(configStorage);
-        return service;
-    }
-
-    // =================== 微信小程序独有 ===================
-
-    @Override
-    public WxMaPhoneNumberInfo getWxMaPhoneNumberInfo(Integer userType, String phoneCode) {
-        WxMaService service = getWxMaService(userType);
-        try {
-            return service.getUserService().getPhoneNoInfo(phoneCode);
-        } catch (WxErrorException e) {
-            log.error("[getPhoneNoInfo][userType({}) phoneCode({}) 获得手机号失败]", userType, phoneCode, e);
-            throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_PHONE_CODE_ERROR);
-        }
-    }
-
-    /**
-     * 获得 clientId + clientSecret 对应的 WxMpService 对象
-     *
-     * @param userType 用户类型
-     * @return WxMpService 对象
-     */
-    @VisibleForTesting
-    WxMaService getWxMaService(Integer userType) {
-        // 第一步,查询 DB 的配置项,获得对应的 WxMaService 对象
-        SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
-                SocialTypeEnum.WECHAT_MINI_APP.getType(), userType);
-        if (client != null && Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
-            return wxMaServiceCache.getUnchecked(client.getClientId() + ":" + client.getClientSecret());
-        }
-        // 第二步,不存在 DB 配置项,则使用 application-*.yaml 对应的 WxMaService 对象
-        return wxMaService;
-    }
-
-    /**
-     * 创建 clientId + clientSecret 对应的 WxMaService 对象
-     *
-     * @param clientId 微信小程序 appId
-     * @param clientSecret 微信小程序 secret
-     * @return WxMaService 对象
-     */
-    private WxMaService buildWxMaService(String clientId, String clientSecret) {
-        // 第一步,创建 WxMaRedisBetterConfigImpl 对象
-        WxMaRedisBetterConfigImpl configStorage = new WxMaRedisBetterConfigImpl(
-                new RedisTemplateWxRedisOps(stringRedisTemplate),
-                wxMaProperties.getConfigStorage().getKeyPrefix());
-        configStorage.setAppid(clientId);
-        configStorage.setSecret(clientSecret);
-
-        // 第二步,创建 WxMpService 对象
-        WxMaService service = new WxMaServiceImpl();
-        service.setWxMaConfig(configStorage);
-        return service;
-    }
-
-    // =================== 客户端管理 ===================
-
-    @Override
-    public Long createSocialClient(SocialClientSaveReqVO createReqVO) {
-        // 校验重复
-        validateSocialClientUnique(null, createReqVO.getUserType(), createReqVO.getSocialType());
-
-        // 插入
-        SocialClientDO client = BeanUtils.toBean(createReqVO, SocialClientDO.class);
-        socialClientMapper.insert(client);
-        return client.getId();
-    }
-
-    @Override
-    public void updateSocialClient(SocialClientSaveReqVO updateReqVO) {
-        // 校验存在
-        validateSocialClientExists(updateReqVO.getId());
-        // 校验重复
-        validateSocialClientUnique(updateReqVO.getId(), updateReqVO.getUserType(), updateReqVO.getSocialType());
-
-        // 更新
-        SocialClientDO updateObj = BeanUtils.toBean(updateReqVO, SocialClientDO.class);
-        socialClientMapper.updateById(updateObj);
-    }
-
-    @Override
-    public void deleteSocialClient(Long id) {
-        // 校验存在
-        validateSocialClientExists(id);
-        // 删除
-        socialClientMapper.deleteById(id);
-    }
-
-    private void validateSocialClientExists(Long id) {
-        if (socialClientMapper.selectById(id) == null) {
-            throw exception(SOCIAL_CLIENT_NOT_EXISTS);
-        }
-    }
-
-    /**
-     * 校验社交应用是否重复,需要保证 userType + socialType 唯一
-     *
-     * 原因是,不同端(userType)选择某个社交登录(socialType)时,需要通过 {@link #buildAuthRequest(Integer, Integer)} 构建对应的请求
-     *
-     * @param id 编号
-     * @param userType 用户类型
-     * @param socialType 社交类型
-     */
-    private void validateSocialClientUnique(Long id, Integer userType, Integer socialType) {
-        SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
-                socialType, userType);
-        if (client == null) {
-            return;
-        }
-        if (id == null // 新增时,说明重复
-                || ObjUtil.notEqual(id, client.getId())) { // 更新时,如果 id 不一致,说明重复
-            throw exception(SOCIAL_CLIENT_UNIQUE);
-        }
-    }
-
-    @Override
-    public SocialClientDO getSocialClient(Long id) {
-        return socialClientMapper.selectById(id);
-    }
-
-    @Override
-    public PageResult<SocialClientDO> getSocialClientPage(SocialClientPageReqVO pageReqVO) {
-        return socialClientMapper.selectPage(pageReqVO);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialUserService.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialUserService.java
deleted file mode 100644
index f017f8d..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialUserService.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.iailab.module.system.service.social;
-
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-
-import javax.validation.Valid;
-import java.util.List;
-
-/**
- * 社交用户 Service 接口,例如说社交平台的授权登录
- *
- * @author iailab
- */
-public interface SocialUserService {
-
-    /**
-     * 获得指定用户的社交用户列表
-     *
-     * @param userId   用户编号
-     * @param userType 用户类型
-     * @return 社交用户列表
-     */
-    List<SocialUserDO> getSocialUserList(Long userId, Integer userType);
-
-    /**
-     * 绑定社交用户
-     *
-     * @param reqDTO 绑定信息
-     * @return 社交用户 openid
-     */
-    String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO);
-
-    /**
-     * 取消绑定社交用户
-     *
-     * @param userId 用户编号
-     * @param userType 全局用户类型
-     * @param socialType 社交平台的类型 {@link SocialTypeEnum}
-     * @param openid 社交平台的 openid
-     */
-    void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid);
-
-    /**
-     * 获得社交用户,基于 userId
-     *
-     * @param userType 用户类型
-     * @param userId 用户编号
-     * @param socialType 社交平台的类型
-     * @return 社交用户
-     */
-    SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType);
-
-    /**
-     * 获得社交用户
-     *
-     * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
-     *
-     * @param userType 用户类型
-     * @param socialType 社交平台的类型
-     * @param code 授权码
-     * @param state state
-     * @return 社交用户
-     */
-    SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state);
-
-    // ==================== 社交用户 CRUD ====================
-
-    /**
-     * 获得社交用户
-     *
-     * @param id 编号
-     * @return 社交用户
-     */
-    SocialUserDO getSocialUser(Long id);
-
-    /**
-     * 获得社交用户分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 社交用户分页
-     */
-    PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO);
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialUserServiceImpl.java b/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialUserServiceImpl.java
deleted file mode 100644
index 177b1b6..0000000
--- a/iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/social/SocialUserServiceImpl.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package com.iailab.module.system.service.social;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Assert;
-import com.iailab.framework.common.exception.ServiceException;
-import com.iailab.framework.common.pojo.PageResult;
-import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
-import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
-import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserBindDO;
-import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
-import com.iailab.module.system.dal.mysql.social.SocialUserBindMapper;
-import com.iailab.module.system.dal.mysql.social.SocialUserMapper;
-import com.iailab.module.system.enums.social.SocialTypeEnum;
-import com.xingyuv.jushauth.model.AuthUser;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.validation.annotation.Validated;
-
-import javax.annotation.Resource;
-import javax.validation.constraints.NotNull;
-import java.util.Collections;
-import java.util.List;
-
-import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet;
-import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
-import static com.iailab.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
-
-/**
- * 社交用户 Service 实现类
- *
- * @author iailab
- */
-@Service
-@Validated
-@Slf4j
-public class SocialUserServiceImpl implements SocialUserService {
-
-    @Resource
-    private SocialUserBindMapper socialUserBindMapper;
-    @Resource
-    private SocialUserMapper socialUserMapper;
-
-    @Resource
-    private SocialClientService socialClientService;
-
-    @Override
-    public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {
-        // 获得绑定
-        List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectListByUserIdAndUserType(userId, userType);
-        if (CollUtil.isEmpty(socialUserBinds)) {
-            return Collections.emptyList();
-        }
-        // 获得社交用户
-        return socialUserMapper.selectBatchIds(convertSet(socialUserBinds, SocialUserBindDO::getSocialUserId));
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
-        // 获得社交用户
-        SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
-                reqDTO.getCode(), reqDTO.getState());
-        Assert.notNull(socialUser, "社交用户不能为空");
-
-        // 社交用户可能之前绑定过别的用户,需要进行解绑
-        socialUserBindMapper.deleteByUserTypeAndSocialUserId(reqDTO.getUserType(), socialUser.getId());
-
-        // 用户可能之前已经绑定过该社交类型,需要进行解绑
-        socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(reqDTO.getUserType(), reqDTO.getUserId(),
-                socialUser.getType());
-
-        // 绑定当前登录的社交用户
-        SocialUserBindDO socialUserBind = SocialUserBindDO.builder()
-                .userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
-                .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build();
-        socialUserBindMapper.insert(socialUserBind);
-        return socialUser.getOpenid();
-    }
-
-    @Override
-    public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) {
-        // 获得 openid 对应的 SocialUserDO 社交用户
-        SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
-        if (socialUser == null) {
-            throw exception(SOCIAL_USER_NOT_FOUND);
-        }
-
-        // 获得对应的社交绑定关系
-        socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(userType, userId, socialUser.getType());
-    }
-
-    @Override
-    public SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType) {
-        // 获得绑定用户
-        SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(userId, userType, socialType);
-        if (socialUserBind == null) {
-            return null;
-        }
-        // 获得社交用户
-        SocialUserDO socialUser = socialUserMapper.selectById(socialUserBind.getSocialUserId());
-        Assert.notNull(socialUser, "社交用户不能为空");
-        return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
-                socialUserBind.getUserId());
-    }
-
-    @Override
-    public SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state) {
-        // 获得社交用户
-        SocialUserDO socialUser = authSocialUser(socialType, userType, code, state);
-        Assert.notNull(socialUser, "社交用户不能为空");
-
-        // 获得绑定用户
-        SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserTypeAndSocialUserId(userType,
-                socialUser.getId());
-        return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
-                socialUserBind != null ? socialUserBind.getUserId() : null);
-    }
-
-    /**
-     * 授权获得对应的社交用户
-     * 如果授权失败,则会抛出 {@link ServiceException} 异常
-     *
-     * @param socialType 社交平台的类型 {@link SocialTypeEnum}
-     * @param userType 用户类型
-     * @param code     授权码
-     * @param state    state
-     * @return 授权用户
-     */
-    @NotNull
-    public SocialUserDO authSocialUser(Integer socialType, Integer userType, String code, String state) {
-        // 优先从 DB 中获取,因为 code 有且可以使用一次。
-        // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
-        SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(socialType, code, state);
-        if (socialUser != null) {
-            return socialUser;
-        }
-
-        // 请求获取
-        AuthUser authUser = socialClientService.getAuthUser(socialType, userType, code, state);
-        Assert.notNull(authUser, "三方用户不能为空");
-
-        // 保存到 DB 中
-        socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, authUser.getUuid());
-        if (socialUser == null) {
-            socialUser = new SocialUserDO();
-        }
-        socialUser.setType(socialType).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询
-                .setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken())))
-                .setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo()));
-        if (socialUser.getId() == null) {
-            socialUserMapper.insert(socialUser);
-        } else {
-            socialUserMapper.updateById(socialUser);
-        }
-        return socialUser;
-    }
-
-    // ==================== 社交用户 CRUD ====================
-
-    @Override
-    public SocialUserDO getSocialUser(Long id) {
-        return socialUserMapper.selectById(id);
-    }
-
-    @Override
-    public PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO) {
-        return socialUserMapper.selectPage(pageReqVO);
-    }
-
-}
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/resources/application-dev.yaml b/iailab-module-system/iailab-module-system-biz/src/main/resources/application-dev.yaml
index 4188c19..3d08576 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/resources/application-dev.yaml
+++ b/iailab-module-system/iailab-module-system-biz/src/main/resources/application-dev.yaml
@@ -39,7 +39,7 @@
       primary: master
       datasource:
         master:
-          url: jdbc:mysql://172.16.8.100:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
+          url: jdbc:mysql://localhost:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
           username: root
           password: 123456
         slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
@@ -64,7 +64,7 @@
 spring:
   # RabbitMQ 配置项,对应 RabbitProperties 配置类
   rabbitmq:
-    host: 172.16.8.200 # RabbitMQ 服务的地址
+    host: 172.16.1.221 # RabbitMQ 服务的地址
     port: 5672 # RabbitMQ 服务的端口
     username: admin # RabbitMQ 服务的账号
     password: admin123 # RabbitMQ 服务的密码
@@ -72,6 +72,13 @@
   kafka:
     bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
 
+--- #################### 定时任务相关配置 ####################
+xxl:
+  job:
+    enabled: true # 是否开启调度中心,默认为 true 开启
+    admin:
+      addresses: http://172.16.216.135:9090/xxl-job-admin # 调度中心部署跟地址
+
 --- #################### 服务保障相关配置 ####################
 
 # Lock4j 配置项
diff --git a/iailab-module-system/iailab-module-system-biz/src/main/resources/application.yaml b/iailab-module-system/iailab-module-system-biz/src/main/resources/application.yaml
index c2167c8..15f0ab1 100644
--- a/iailab-module-system/iailab-module-system-biz/src/main/resources/application.yaml
+++ b/iailab-module-system/iailab-module-system-biz/src/main/resources/application.yaml
@@ -12,6 +12,7 @@
       username: @nacos.username@
       password: @nacos.password@
       discovery: # 【配置中心】配置项
+#        ip: 172.16.8.200
         namespace: @profiles.active@
         group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
         metadata:
@@ -155,6 +156,16 @@
     req-check-minute-limit: 60 # check 接口一分钟内请求数限制
     req-verify-minute-limit: 60 # verify 接口一分钟内请求数限制
 
+--- #################### 定时任务相关配置 ####################
+
+xxl:
+  job:
+    executor:
+#      ip: 172.16.8.200
+      appname: ${spring.application.name} # 执行器 AppName
+      logpath: D:/DLUT/IailabPlat/webapp/infra/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
+    accessToken: default_token # 执行器通讯TOKEN
+
 --- #################### 平台相关配置 ####################
 
 iailab:
diff --git a/iailab-plat-sdk/src/main/java/com/iailab/sdk/auth/client/IailabClient.java b/iailab-plat-sdk/src/main/java/com/iailab/sdk/auth/client/IailabClient.java
index 96b3342..ce84464 100644
--- a/iailab-plat-sdk/src/main/java/com/iailab/sdk/auth/client/IailabClient.java
+++ b/iailab-plat-sdk/src/main/java/com/iailab/sdk/auth/client/IailabClient.java
@@ -80,7 +80,7 @@
     private static final String RESP_DATA = "data";
 
     /**
-     * 用户名密码方式获取平台token
+     * 客户端方式获取平台token
      */
     public static synchronized TokenDTO authenticate() {
         System.out.println("登录获取平台token");
diff --git a/pom.xml b/pom.xml
index fb75d8b..c396f1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,6 @@
     <version>${revision}</version>
     <packaging>pom</packaging>
     <modules>
-        <module>iailab-framework</module>
         <module>iailab-cloud</module>
         <!--  各种 module 拓展 -->
         <module>iailab-module-system</module>
@@ -17,6 +16,7 @@
         <module>iailab-module-report</module>
         <module>iailab-module-data</module>
         <module>iailab-module-model</module>
+        <module>iailab-plat-sdk</module>
     </modules>
 
     <name>${project.artifactId}</name>
@@ -97,7 +97,7 @@
         <okhttp3.version>4.11.0</okhttp3.version>
         <commons-io.version>2.15.1</commons-io.version>
         <minio.version>8.5.7</minio.version>
-        <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version>
+<!--        <aliyun-java-sdk-core.version>4.6.4</aliyun-java-sdk-core.version>-->
         <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
         <tencentcloud-sdk-java.version>3.1.880</tencentcloud-sdk-java.version>
         <justauth.version>1.0.8</justauth.version>
@@ -114,7 +114,7 @@
             <properties>
                 <!-- 环境标识,需要与配置文件的名称相对应 -->
                 <profiles.active>dev</profiles.active>
-                <nacos.server>127.0.0.1:8848</nacos.server>
+                <nacos.server>localhost:8848</nacos.server>
                 <nacos.discovery.group>DEFAULT_GROUP</nacos.discovery.group>
                 <nacos.config.group>DEFAULT_GROUP</nacos.config.group>
                 <nacos.username>nacos</nacos.username>
@@ -122,7 +122,7 @@
                 <nacos.metadata.version>1.0.0</nacos.metadata.version>
                 <log.path>D:/DLUT/iailab-plat</log.path>
                 <logstash.address>127.0.0.1:4560</logstash.address>
-                <deploy.server>127.0.0.1</deploy.server>
+                <deploy.server>192.168.56.1</deploy.server>
             </properties>
             <activation>
                 <!-- 默认环境 -->
@@ -154,25 +154,25 @@
                 <nacos.discovery.group>DEFAULT_GROUP</nacos.discovery.group>
                 <nacos.config.group>DEFAULT_GROUP</nacos.config.group>
                 <nacos.username>nacos</nacos.username>
-                <nacos.password>nacos</nacos.password>
+                <nacos.password>fG2@jH6#kI</nacos.password>
                 <nacos.metadata.version>1.0.0</nacos.metadata.version>
                 <log.path>.</log.path>
                 <logstash.address>127.0.0.1:4560</logstash.address>
-                <deploy.server>10.88.4.131</deploy.server>
+                <deploy.server>10.200.25.49</deploy.server>
             </properties>
         </profile>
     </profiles>
 
     <dependencyManagement>
         <dependencies>
-            <!-- 统一依赖管理 -->
-            <dependency>
-                <groupId>io.netty</groupId>
-                <artifactId>netty-bom</artifactId>
-                <version>${netty.version}</version>
-                <type>pom</type>
-                <scope>import</scope>
-            </dependency>
+<!--            &lt;!&ndash; 统一依赖管理 &ndash;&gt;-->
+<!--            <dependency>-->
+<!--                <groupId>io.netty</groupId>-->
+<!--                <artifactId>netty-bom</artifactId>-->
+<!--                <version>${netty.version}</version>-->
+<!--                <type>pom</type>-->
+<!--                <scope>import</scope>-->
+<!--            </dependency>-->
             <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-framework-bom</artifactId> <!-- JDK8 版本独有:保证 Spring Framework 尽量高 -->
@@ -209,18 +209,18 @@
                 <scope>import</scope>
             </dependency>
 
-            <!-- 业务组件 -->
-            <dependency>
-                <groupId>io.github.mouzt</groupId>
-                <artifactId>bizlog-sdk</artifactId>
-                <version>${bizlog-sdk.version}</version>
-                <exclusions>
-                    <exclusion> <!-- 排除掉springboot依赖使用项目的 -->
-                        <groupId>org.springframework.boot</groupId>
-                        <artifactId>spring-boot-starter</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
+<!--            &lt;!&ndash; 业务组件 &ndash;&gt;-->
+<!--            <dependency>-->
+<!--                <groupId>io.github.mouzt</groupId>-->
+<!--                <artifactId>bizlog-sdk</artifactId>-->
+<!--                <version>${bizlog-sdk.version}</version>-->
+<!--                <exclusions>-->
+<!--                    <exclusion> &lt;!&ndash; 排除掉springboot依赖使用项目的 &ndash;&gt;-->
+<!--                        <groupId>org.springframework.boot</groupId>-->
+<!--                        <artifactId>spring-boot-starter</artifactId>-->
+<!--                    </exclusion>-->
+<!--                </exclusions>-->
+<!--            </dependency>-->
             <dependency>
                 <groupId>com.iailab</groupId>
                 <artifactId>iailab-common-biz-tenant</artifactId>
@@ -237,13 +237,13 @@
                 <version>${revision}</version>
             </dependency>
 
-            <!-- Spring 核心 -->
-            <dependency>
-                <!-- 用于生成自定义的 Spring @ConfigurationProperties 配置类的说明文件 -->
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-configuration-processor</artifactId>
-                <version>${spring.boot.version}</version>
-            </dependency>
+<!--            &lt;!&ndash; Spring 核心 &ndash;&gt;-->
+<!--            <dependency>-->
+<!--                &lt;!&ndash; 用于生成自定义的 Spring @ConfigurationProperties 配置类的说明文件 &ndash;&gt;-->
+<!--                <groupId>org.springframework.boot</groupId>-->
+<!--                <artifactId>spring-boot-configuration-processor</artifactId>-->
+<!--                <version>${spring.boot.version}</version>-->
+<!--            </dependency>-->
 
             <dependency>
                 <groupId>com.iailab</groupId>
@@ -286,48 +286,48 @@
                 <version>${knife4j.version}</version>
             </dependency>
 
-            <!-- DB 相关 -->
-            <dependency>
-                <groupId>org.postgresql</groupId>
-                <artifactId>postgresql</artifactId>
-                <version>${postgresql.version}</version>
-            </dependency>
+<!--            &lt;!&ndash; DB 相关 &ndash;&gt;-->
+<!--            <dependency>-->
+<!--                <groupId>org.postgresql</groupId>-->
+<!--                <artifactId>postgresql</artifactId>-->
+<!--                <version>${postgresql.version}</version>-->
+<!--            </dependency>-->
             <dependency>
                 <groupId>com.iailab</groupId>
                 <artifactId>iailab-common-mybatis</artifactId>
                 <version>${revision}</version>
             </dependency>
-            <dependency>
-                <groupId>org.springdoc</groupId>
-                <artifactId>springdoc-openapi-webflux-ui</artifactId>
-                <version>${springdoc.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.springdoc</groupId>-->
+<!--                <artifactId>springdoc-openapi-webflux-ui</artifactId>-->
+<!--                <version>${springdoc.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>com.alibaba</groupId>
-                <artifactId>druid-spring-boot-starter</artifactId>
-                <version>${druid.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.baomidou</groupId>
-                <artifactId>mybatis-plus-boot-starter</artifactId>
-                <version>${mybatis-plus.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.alibaba</groupId>-->
+<!--                <artifactId>druid-spring-boot-starter</artifactId>-->
+<!--                <version>${druid.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.baomidou</groupId>-->
+<!--                <artifactId>mybatis-plus-boot-starter</artifactId>-->
+<!--                <version>${mybatis-plus.version}</version>-->
+<!--            </dependency>-->
             <dependency>
                 <groupId>com.baomidou</groupId>
                 <artifactId>mybatis-plus-generator</artifactId> <!-- 代码生成器,使用它解析表结构 -->
                 <version>${mybatis-plus-generator.version}</version>
             </dependency>
-            <dependency>
-                <groupId>com.baomidou</groupId>
-                <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
-                <version>${dynamic-datasource.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.github.yulichang</groupId>
-                <artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 -->
-                <version>${mybatis-plus-join.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.baomidou</groupId>-->
+<!--                <artifactId>dynamic-datasource-spring-boot-starter</artifactId> &lt;!&ndash; 多数据源 &ndash;&gt;-->
+<!--                <version>${dynamic-datasource.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.github.yulichang</groupId>-->
+<!--                <artifactId>mybatis-plus-join-boot-starter</artifactId> &lt;!&ndash; MyBatis 联表查询 &ndash;&gt;-->
+<!--                <version>${mybatis-plus-join.version}</version>-->
+<!--            </dependency>-->
 
             <dependency>
                 <groupId>com.iailab</groupId>
@@ -335,43 +335,43 @@
                 <version>${revision}</version>
             </dependency>
 
-            <dependency>
-                <groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
-                <artifactId>easy-trans-spring-boot-starter</artifactId>
-                <version>${easy-trans.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.springframework</groupId>
-                        <artifactId>spring-context</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.springframework.cloud</groupId>
-                        <artifactId>spring-cloud-commons</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>com.fhs-opensource</groupId>
-                <artifactId>easy-trans-mybatis-plus-extend</artifactId>
-                <version>${easy-trans.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.fhs-opensource</groupId>
-                <artifactId>easy-trans-anno</artifactId>
-                <version>${easy-trans.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.fhs-opensource</groupId> &lt;!&ndash; VO 数据翻译 &ndash;&gt;-->
+<!--                <artifactId>easy-trans-spring-boot-starter</artifactId>-->
+<!--                <version>${easy-trans.version}</version>-->
+<!--                <exclusions>-->
+<!--                    <exclusion>-->
+<!--                        <groupId>org.springframework</groupId>-->
+<!--                        <artifactId>spring-context</artifactId>-->
+<!--                    </exclusion>-->
+<!--                    <exclusion>-->
+<!--                        <groupId>org.springframework.cloud</groupId>-->
+<!--                        <artifactId>spring-cloud-commons</artifactId>-->
+<!--                    </exclusion>-->
+<!--                </exclusions>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.fhs-opensource</groupId>-->
+<!--                <artifactId>easy-trans-mybatis-plus-extend</artifactId>-->
+<!--                <version>${easy-trans.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.fhs-opensource</groupId>-->
+<!--                <artifactId>easy-trans-anno</artifactId>-->
+<!--                <version>${easy-trans.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>org.redisson</groupId>
-                <artifactId>redisson-spring-boot-starter</artifactId>
-                <version>${redisson.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.redisson</groupId>-->
+<!--                <artifactId>redisson-spring-boot-starter</artifactId>-->
+<!--                <version>${redisson.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>com.dameng</groupId>
-                <artifactId>DmJdbcDriver18</artifactId>
-                <version>${dm8.jdbc.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.dameng</groupId>-->
+<!--                <artifactId>DmJdbcDriver18</artifactId>-->
+<!--                <version>${dm8.jdbc.version}</version>-->
+<!--            </dependency>-->
 
             <!-- RPC 远程调用相关 -->
             <dependency>
@@ -380,9 +380,9 @@
                 <version>${revision}</version>
             </dependency>
 
-            <!-- Registry 注册中心相关 -->
+<!--            &lt;!&ndash; Registry 注册中心相关 &ndash;&gt;-->
 
-            <!-- Config 配置中心相关 -->
+<!--            &lt;!&ndash; Config 配置中心相关 &ndash;&gt;-->
 
             <!-- Job 定时任务相关 -->
             <dependency>
@@ -403,11 +403,11 @@
                 <version>${revision}</version>
             </dependency>
 
-            <dependency>
-                <groupId>org.apache.rocketmq</groupId>
-                <artifactId>rocketmq-spring-boot-starter</artifactId>
-                <version>${rocketmq-spring.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.apache.rocketmq</groupId>-->
+<!--                <artifactId>rocketmq-spring-boot-starter</artifactId>-->
+<!--                <version>${rocketmq-spring.version}</version>-->
+<!--            </dependency>-->
 
             <!-- 服务保障相关 -->
             <dependency>
@@ -416,17 +416,17 @@
                 <version>${revision}</version>
             </dependency>
 
-            <dependency>
-                <groupId>com.baomidou</groupId>
-                <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
-                <version>${lock4j.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <artifactId>redisson-spring-boot-starter</artifactId>
-                        <groupId>org.redisson</groupId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.baomidou</groupId>-->
+<!--                <artifactId>lock4j-redisson-spring-boot-starter</artifactId>-->
+<!--                <version>${lock4j.version}</version>-->
+<!--                <exclusions>-->
+<!--                    <exclusion>-->
+<!--                        <artifactId>redisson-spring-boot-starter</artifactId>-->
+<!--                        <groupId>org.redisson</groupId>-->
+<!--                    </exclusion>-->
+<!--                </exclusions>-->
+<!--            </dependency>-->
 
             <!-- 监控相关 -->
             <dependency>
@@ -435,57 +435,57 @@
                 <version>${revision}</version>
             </dependency>
 
-            <dependency>
-                <groupId>org.apache.skywalking</groupId>
-                <artifactId>apm-toolkit-trace</artifactId>
-                <version>${skywalking.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.skywalking</groupId>
-                <artifactId>apm-toolkit-logback-1.x</artifactId>
-                <version>${skywalking.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.skywalking</groupId>
-                <artifactId>apm-toolkit-opentracing</artifactId>
-                <version>${skywalking.version}</version>
-                <!--                <exclusions>-->
-                <!--                    <exclusion>-->
-                <!--                        <artifactId>opentracing-api</artifactId>-->
-                <!--                        <groupId>io.opentracing</groupId>-->
-                <!--                    </exclusion>-->
-                <!--                    <exclusion>-->
-                <!--                        <artifactId>opentracing-util</artifactId>-->
-                <!--                        <groupId>io.opentracing</groupId>-->
-                <!--                    </exclusion>-->
-                <!--                </exclusions>-->
-            </dependency>
-            <dependency>
-                <groupId>io.opentracing</groupId>
-                <artifactId>opentracing-api</artifactId>
-                <version>${opentracing.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.opentracing</groupId>
-                <artifactId>opentracing-util</artifactId>
-                <version>${opentracing.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>io.opentracing</groupId>
-                <artifactId>opentracing-noop</artifactId>
-                <version>${opentracing.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.apache.skywalking</groupId>-->
+<!--                <artifactId>apm-toolkit-trace</artifactId>-->
+<!--                <version>${skywalking.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>org.apache.skywalking</groupId>-->
+<!--                <artifactId>apm-toolkit-logback-1.x</artifactId>-->
+<!--                <version>${skywalking.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>org.apache.skywalking</groupId>-->
+<!--                <artifactId>apm-toolkit-opentracing</artifactId>-->
+<!--                <version>${skywalking.version}</version>-->
+<!--                &lt;!&ndash;                <exclusions>&ndash;&gt;-->
+<!--                &lt;!&ndash;                    <exclusion>&ndash;&gt;-->
+<!--                &lt;!&ndash;                        <artifactId>opentracing-api</artifactId>&ndash;&gt;-->
+<!--                &lt;!&ndash;                        <groupId>io.opentracing</groupId>&ndash;&gt;-->
+<!--                &lt;!&ndash;                    </exclusion>&ndash;&gt;-->
+<!--                &lt;!&ndash;                    <exclusion>&ndash;&gt;-->
+<!--                &lt;!&ndash;                        <artifactId>opentracing-util</artifactId>&ndash;&gt;-->
+<!--                &lt;!&ndash;                        <groupId>io.opentracing</groupId>&ndash;&gt;-->
+<!--                &lt;!&ndash;                    </exclusion>&ndash;&gt;-->
+<!--                &lt;!&ndash;                </exclusions>&ndash;&gt;-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>io.opentracing</groupId>-->
+<!--                <artifactId>opentracing-api</artifactId>-->
+<!--                <version>${opentracing.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>io.opentracing</groupId>-->
+<!--                <artifactId>opentracing-util</artifactId>-->
+<!--                <version>${opentracing.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>io.opentracing</groupId>-->
+<!--                <artifactId>opentracing-noop</artifactId>-->
+<!--                <version>${opentracing.version}</version>-->
+<!--            </dependency>-->
 
             <dependency>
                 <groupId>de.codecentric</groupId>
                 <artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
                 <version>${spring-boot-admin.version}</version>
             </dependency>
-            <dependency>
-                <groupId>de.codecentric</groupId>
-                <artifactId>spring-boot-admin-starter-client</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 -->
-                <version>${spring-boot-admin.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>de.codecentric</groupId>-->
+<!--                <artifactId>spring-boot-admin-starter-client</artifactId> &lt;!&ndash; 实现 Spring Boot Admin Server 服务端 &ndash;&gt;-->
+<!--                <version>${spring-boot-admin.version}</version>-->
+<!--            </dependency>-->
 
             <!-- Test 测试相关 -->
             <dependency>
@@ -495,39 +495,39 @@
                 <scope>test</scope>
             </dependency>
 
-            <dependency>
-                <groupId>org.mockito</groupId>
-                <artifactId>mockito-inline</artifactId>
-                <version>${mockito-inline.version}</version> <!-- 支持 Mockito 的 final 类与 static 方法的 mock -->
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.mockito</groupId>-->
+<!--                <artifactId>mockito-inline</artifactId>-->
+<!--                <version>${mockito-inline.version}</version> &lt;!&ndash; 支持 Mockito 的 final 类与 static 方法的 mock &ndash;&gt;-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-starter-test</artifactId>
-                <version>${spring.boot.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <artifactId>asm</artifactId>
-                        <groupId>org.ow2.asm</groupId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.mockito</groupId>
-                        <artifactId>mockito-core</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.springframework.boot</groupId>-->
+<!--                <artifactId>spring-boot-starter-test</artifactId>-->
+<!--                <version>${spring.boot.version}</version>-->
+<!--                <exclusions>-->
+<!--                    <exclusion>-->
+<!--                        <artifactId>asm</artifactId>-->
+<!--                        <groupId>org.ow2.asm</groupId>-->
+<!--                    </exclusion>-->
+<!--                    <exclusion>-->
+<!--                        <groupId>org.mockito</groupId>-->
+<!--                        <artifactId>mockito-core</artifactId>-->
+<!--                    </exclusion>-->
+<!--                </exclusions>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>com.github.fppt</groupId> <!-- 单元测试,我们采用内嵌的 Redis 数据库 -->
-                <artifactId>jedis-mock</artifactId>
-                <version>${jedis-mock.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.github.fppt</groupId> &lt;!&ndash; 单元测试,我们采用内嵌的 Redis 数据库 &ndash;&gt;-->
+<!--                <artifactId>jedis-mock</artifactId>-->
+<!--                <version>${jedis-mock.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>uk.co.jemos.podam</groupId> <!-- 单元测试,随机生成 POJO 类 -->
-                <artifactId>podam</artifactId>
-                <version>${podam.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>uk.co.jemos.podam</groupId> &lt;!&ndash; 单元测试,随机生成 POJO 类 &ndash;&gt;-->
+<!--                <artifactId>podam</artifactId>-->
+<!--                <version>${podam.version}</version>-->
+<!--            </dependency>-->
 
             <!-- 工作流相关 -->
             <dependency>
@@ -555,51 +555,51 @@
                 <version>${revision}</version>
             </dependency>
 
-            <dependency>
-                <groupId>org.projectlombok</groupId>
-                <artifactId>lombok</artifactId>
-                <version>${lombok.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.projectlombok</groupId>-->
+<!--                <artifactId>lombok</artifactId>-->
+<!--                <version>${lombok.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>org.mapstruct</groupId>
-                <artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
-                <version>${mapstruct.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.mapstruct</groupId>
-                <artifactId>mapstruct-jdk8</artifactId>
-                <version>${mapstruct.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.mapstruct</groupId>
-                <artifactId>mapstruct-processor</artifactId>
-                <version>${mapstruct.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.mapstruct</groupId>-->
+<!--                <artifactId>mapstruct</artifactId> &lt;!&ndash; use mapstruct-jdk8 for Java 8 or higher &ndash;&gt;-->
+<!--                <version>${mapstruct.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>org.mapstruct</groupId>-->
+<!--                <artifactId>mapstruct-jdk8</artifactId>-->
+<!--                <version>${mapstruct.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>org.mapstruct</groupId>-->
+<!--                <artifactId>mapstruct-processor</artifactId>-->
+<!--                <version>${mapstruct.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>cn.hutool</groupId>
-                <artifactId>hutool-all</artifactId>
-                <version>${hutool.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>cn.hutool</groupId>-->
+<!--                <artifactId>hutool-all</artifactId>-->
+<!--                <version>${hutool.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>joda-time</groupId>
-                <artifactId>joda-time</artifactId>
-                <version>${joda.time.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>joda-time</groupId>-->
+<!--                <artifactId>joda-time</artifactId>-->
+<!--                <version>${joda.time.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>com.alibaba</groupId>
-                <artifactId>easyexcel</artifactId>
-                <version>${easyexcel.verion}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.alibaba</groupId>-->
+<!--                <artifactId>easyexcel</artifactId>-->
+<!--                <version>${easyexcel.verion}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>commons-io</groupId>
-                <artifactId>commons-io</artifactId>
-                <version>${commons-io.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>commons-io</groupId>-->
+<!--                <artifactId>commons-io</artifactId>-->
+<!--                <version>${commons-io.version}</version>-->
+<!--            </dependency>-->
 
             <dependency>
                 <groupId>org.apache.tika</groupId>
@@ -613,27 +613,27 @@
                 <version>${velocity.version}</version>
             </dependency>
 
-            <dependency>
-                <groupId>com.alibaba</groupId>
-                <artifactId>fastjson</artifactId>
-                <version>${fastjson.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.alibaba</groupId>-->
+<!--                <artifactId>fastjson</artifactId>-->
+<!--                <version>${fastjson.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>cn.smallbun.screw</groupId>
-                <artifactId>screw-core</artifactId> <!-- 实现数据库文档 -->
-                <version>${screw.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.freemarker</groupId>
-                        <artifactId>freemarker</artifactId> <!-- 移除 Freemarker 依赖,采用 Velocity 作为模板引擎 -->
-                    </exclusion>
-                    <exclusion>
-                        <groupId>com.alibaba</groupId>
-                        <artifactId>fastjson</artifactId> <!-- 最新版screw-core1.0.5依赖fastjson1.2.73存在漏洞,移除。 -->
-                    </exclusion>
-                </exclusions>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>cn.smallbun.screw</groupId>-->
+<!--                <artifactId>screw-core</artifactId> &lt;!&ndash; 实现数据库文档 &ndash;&gt;-->
+<!--                <version>${screw.version}</version>-->
+<!--                <exclusions>-->
+<!--                    <exclusion>-->
+<!--                        <groupId>org.freemarker</groupId>-->
+<!--                        <artifactId>freemarker</artifactId> &lt;!&ndash; 移除 Freemarker 依赖,采用 Velocity 作为模板引擎 &ndash;&gt;-->
+<!--                    </exclusion>-->
+<!--                    <exclusion>-->
+<!--                        <groupId>com.alibaba</groupId>-->
+<!--                        <artifactId>fastjson</artifactId> &lt;!&ndash; 最新版screw-core1.0.5依赖fastjson1.2.73存在漏洞,移除。 &ndash;&gt;-->
+<!--                    </exclusion>-->
+<!--                </exclusions>-->
+<!--            </dependency>-->
 
             <dependency>
                 <groupId>com.google.guava</groupId>
@@ -641,17 +641,17 @@
                 <version>${guava.version}</version>
             </dependency>
 
-            <dependency>
-                <groupId>com.google.inject</groupId>
-                <artifactId>guice</artifactId>
-                <version>${guice.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.google.inject</groupId>-->
+<!--                <artifactId>guice</artifactId>-->
+<!--                <version>${guice.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>com.alibaba</groupId>
-                <artifactId>transmittable-thread-local</artifactId> <!-- 解决 ThreadLocal 父子线程的传值问题 -->
-                <version>${transmittable-thread-local.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>com.alibaba</groupId>-->
+<!--                <artifactId>transmittable-thread-local</artifactId> &lt;!&ndash; 解决 ThreadLocal 父子线程的传值问题 &ndash;&gt;-->
+<!--                <version>${transmittable-thread-local.version}</version>-->
+<!--            </dependency>-->
 
             <dependency>
                 <groupId>commons-net</groupId>
@@ -670,84 +670,68 @@
                 <version>${captcha-plus.version}</version>
             </dependency>
 
-            <dependency>
-                <groupId>org.lionsoul</groupId>
-                <artifactId>ip2region</artifactId>
-                <version>${ip2region.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.lionsoul</groupId>-->
+<!--                <artifactId>ip2region</artifactId>-->
+<!--                <version>${ip2region.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>org.jsoup</groupId>
-                <artifactId>jsoup</artifactId>
-                <version>${jsoup.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.jsoup</groupId>-->
+<!--                <artifactId>jsoup</artifactId>-->
+<!--                <version>${jsoup.version}</version>-->
+<!--            </dependency>-->
 
-            <dependency>
-                <groupId>org.reflections</groupId>
-                <artifactId>reflections</artifactId>
-                <version>${reflections.version}</version>
-            </dependency>
+<!--            <dependency>-->
+<!--                <groupId>org.reflections</groupId>-->
+<!--                <artifactId>reflections</artifactId>-->
+<!--                <version>${reflections.version}</version>-->
+<!--            </dependency>-->
 
-            <!-- 三方云服务相关 -->
-            <dependency>
-                <groupId>com.squareup.okio</groupId>
-                <artifactId>okio</artifactId>
-                <version>${okio.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.squareup.okhttp3</groupId>
-                <artifactId>okhttp</artifactId>
-                <version>${okhttp3.version}</version>
-            </dependency>
+<!--            &lt;!&ndash; 三方云服务相关 &ndash;&gt;-->
+<!--            <dependency>-->
+<!--                <groupId>com.squareup.okio</groupId>-->
+<!--                <artifactId>okio</artifactId>-->
+<!--                <version>${okio.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.squareup.okhttp3</groupId>-->
+<!--                <artifactId>okhttp</artifactId>-->
+<!--                <version>${okhttp3.version}</version>-->
+<!--            </dependency>-->
             <dependency>
                 <groupId>io.minio</groupId>
                 <artifactId>minio</artifactId>
                 <version>${minio.version}</version>
             </dependency>
 
-            <dependency>
-                <groupId>com.github.binarywang</groupId>
-                <artifactId>weixin-java-pay</artifactId>
-                <version>${weixin-java.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.github.binarywang</groupId>
-                <artifactId>wx-java-mp-spring-boot-starter</artifactId>
-                <version>${weixin-java.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.github.binarywang</groupId>
-                <artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
-                <version>${weixin-java.version}</version>
-            </dependency>
-
-            <!-- SMS SDK begin -->
-            <dependency>
-                <groupId>com.aliyun</groupId>
-                <artifactId>aliyun-java-sdk-core</artifactId>
-                <version>${aliyun-java-sdk-core.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <artifactId>opentracing-api</artifactId>
-                        <groupId>io.opentracing</groupId>
-                    </exclusion>
-                    <exclusion>
-                        <artifactId>opentracing-util</artifactId>
-                        <groupId>io.opentracing</groupId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>com.aliyun</groupId>
-                <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
-                <version>${aliyun-java-sdk-dysmsapi.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>com.tencentcloudapi</groupId>
-                <artifactId>tencentcloud-sdk-java-sms</artifactId>
-                <version>${tencentcloud-sdk-java.version}</version>
-            </dependency>
-            <!-- SMS SDK end -->
+<!--            &lt;!&ndash; SMS SDK begin &ndash;&gt;-->
+<!--            <dependency>-->
+<!--                <groupId>com.aliyun</groupId>-->
+<!--                <artifactId>aliyun-java-sdk-core</artifactId>-->
+<!--                <version>${aliyun-java-sdk-core.version}</version>-->
+<!--                <exclusions>-->
+<!--                    <exclusion>-->
+<!--                        <artifactId>opentracing-api</artifactId>-->
+<!--                        <groupId>io.opentracing</groupId>-->
+<!--                    </exclusion>-->
+<!--                    <exclusion>-->
+<!--                        <artifactId>opentracing-util</artifactId>-->
+<!--                        <groupId>io.opentracing</groupId>-->
+<!--                    </exclusion>-->
+<!--                </exclusions>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.aliyun</groupId>-->
+<!--                <artifactId>aliyun-java-sdk-dysmsapi</artifactId>-->
+<!--                <version>${aliyun-java-sdk-dysmsapi.version}</version>-->
+<!--            </dependency>-->
+<!--            <dependency>-->
+<!--                <groupId>com.tencentcloudapi</groupId>-->
+<!--                <artifactId>tencentcloud-sdk-java-sms</artifactId>-->
+<!--                <version>${tencentcloud-sdk-java.version}</version>-->
+<!--            </dependency>-->
+<!--            &lt;!&ndash; SMS SDK end &ndash;&gt;-->
 
             <dependency>
                 <groupId>com.xingyuv</groupId>
@@ -898,14 +882,5 @@
             <url>http://172.16.8.100:8090/repository/iailab-snapshots/</url>
         </snapshotRepository>
     </distributionManagement>
-
-    <!-- 使用 iailab 私有云 -->
-<!--    <repositories>-->
-<!--        <repository>-->
-<!--            <id>iailab</id>-->
-<!--            <name>iailab</name>-->
-<!--            <url>http://172.16.8.100:8090/repository/iailab</url>-->
-<!--        </repository>-->
-<!--    </repositories>-->
 
 </project>

--
Gitblit v1.9.3