From 4ce596aa9c2d74e58cb0789e30162a27fbd8701d Mon Sep 17 00:00:00 2001
From: 疯狂的狮子Li <15040126243@163.com>
Date: 星期三, 18 一月 2023 20:44:22 +0800
Subject: [PATCH] !277 项目结构重构 Merge pull request !277 from MichelleChung/5.X

---
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java                                            |  278 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/reflect/ReflectUtils.java                                        |   56 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java                                         |  169 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java                                                      |  192 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/FilterConfig.java                                                 |   55 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java                                                                |   60 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/package-info.java                                                            |    0 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/interceptor/PlusWebInvokeTimeInterceptor.java                            |   94 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/RedisUtils.java                                                |  462 +
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java                                         |   53 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java                                             |  133 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java                      |   18 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/OperatorType.java                                                  |   23 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java                                                    |   37 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaHeaderProcessor.java           |    0 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java                                               |   87 
 ruoyi-common/ruoyi-common-mail/pom.xml                                                                                                    |   31 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java                                          |  461 +
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java                                                  |   76 
 ruoyi-common/ruoyi-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports       |    1 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/Threads.java                                                     |   75 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysLoginController.java                                                                |    4 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/EditGroup.java                                                |    0 
 ruoyi-common/ruoyi-common-oss/pom.xml                                                                                                     |   36 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm                                                                   |    0 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml                                                         |    0 
 pom.xml                                                                                                                                   |   85 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java                                                    |  294 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java                                        |  128 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java                                                        |   89 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java                                                         |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java                                                         |  100 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataScopeService.java                                               |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java                                 |   90 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java                                                  |   16 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm                                                                   |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java                                      |   80 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java                                                         |    0 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssHttpServletRequestWrapper.java                                 |   97 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java                                                   |   13 
 ruoyi-common/ruoyi-common-mybatis/pom.xml                                                                                                 |   48 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java                                                             |  160 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java                                                         |   37 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java                                                  |   26 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/interceptor/PlusDataPermissionInterceptor.java                   |  108 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java                                              |   52 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java                                                  |   79 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java                                                          |   58 
 ruoyi-modules/ruoyi-system/pom.xml                                                                                                        |   80 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java                                            |  118 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/SensitiveService.java                                          |    0 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java                                                |  223 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/CaptchaProperties.java                                 |   38 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java                                                   |    0 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java                                                     |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java                                      |  155 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml                                                         |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java                                                 |   13 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java                                           |   49 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml                                                       |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/TreeBuildUtils.java                                              |   35 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java                                              |   19 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java                                                  |   96 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java                                                |   28 
 ruoyi-common/ruoyi-common-bom/pom.xml                                                                                                     |  129 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java                                                  |   71 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HttpStatus.java                                               |   93 
 ruoyi-common/ruoyi-common-dict/pom.xml                                                                                                    |   26 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java                                         |  141 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java                                                   |  107 
 ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/properties/MailProperties.java                                  |   71 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheNames.java                                               |   48 
 ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports     |    1 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java                                                             |   78 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java                                        |   90 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm                                                                     |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java                                            |  488 +
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java                                               |  110 
 ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports         |    5 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaCategory.java                                               |   35 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java                                                          |   21 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/TreeEntity.java                                             |   41 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java                            |  137 
 ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java                                                                               |    2 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/properties/ThreadPoolProperties.java                            |   32 
 ruoyi-common/ruoyi-common-ratelimiter/pom.xml                                                                                             |   31 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java                                                |   95 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java                                              |    0 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataPermissionHelper.java                                 |   47 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/manager/PlusSpringCacheManager.java                                  |  191 
 ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml                                                      |  220 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessType.java                                                  |   58 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java                                               |    0 
 ruoyi-common/ruoyi-common-web/pom.xml                                                                                                     |   58 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java                                                           |   47 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelListener.java                                              |   14 
 ruoyi-modules/ruoyi-generator/pom.xml                                                                                                     |   48 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml                                                             |    0 
 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java                                     |   53 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java                                                       |   87 
 ruoyi-common/ruoyi-common-idempotent/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports  |    1 
 ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaPermissionImpl.java                               |   49 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java                                                              |   50 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java                                                  |   32 
 ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports         |    1 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataBaseType.java                                          |   49 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/OperLogEvent.java                                                  |  106 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm                                                              |  134 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java                                                           |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java                                                           |   61 
 ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfig.java                                        |   23 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm                                                                     |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/ConfigService.java                                             |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java                                                 |   53 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java                                             |   35 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java                                       |   26 
 ruoyi-common/ruoyi-common-sms/pom.xml                                                                                                     |   37 
 ruoyi-common/ruoyi-common-doc/pom.xml                                                                                                     |   36 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/package-info.java                                                      |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java                                   |  105 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java                                                         |    0 
 ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java                                     |  178 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java                                      |   79 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java                                                   |   13 
 ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/MailUtils.java                                                   |  468 +
 ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java                                                                                |    2 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml                                                         |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java                                         |    0 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelResult.java                                                |   26 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java                                                 |   24 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java                                                  |  107 
 ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports    |    2 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java                                                       |   76 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ValidatorUtils.java                                              |   28 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java               |   18 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java                                                     |    0 
 ruoyi-modules/ruoyi-demo/pom.xml                                                                                                          |   75 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java                                                        |   13 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml                                                         |    0 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java                                             |   75 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/entity/SmsResult.java                                                    |   31 
 ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java                                 |  101 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java                                         |  114 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/CacheUtils.java                                                |   75 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml                                                             |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java                                            |  184 
 ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/config/RateLimiterConfig.java                            |   20 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java                                                  |   94 
 ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports     |    2 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java                                                |   54 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java                                                         |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java                                                   |  168 
 ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml                                                |   92 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/LoginType.java                                                   |   39 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml                                                             |    0 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java                                                 |   90 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java                                       |   89 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java                                               |    0 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm                                                                      |    0 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java                                                    |   35 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/domain.java.vm                                                                   |   57 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java                                    |   74 
 ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerConfig.java                                                |  125 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java                                    |  125 
 ruoyi-modules/ruoyi-demo/src/main/resources/excel/单列表.xlsx                                                                                |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java                             |   18 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java                                                   |   17 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/SensitiveJsonSerializer.java                                   |   54 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefaultExcelListener.java                                       |  106 
 ruoyi-common/ruoyi-common-core/pom.xml                                                                                                    |  115 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java                                        |  115 
 ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml                                                                |    0 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataColumn.java                                       |   28 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java                                            |   58 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java                                      |   20 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java                                                       |    0 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java                                                       |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/RuoYiConfig.java                                                |   54 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/service.java.vm                                                                  |   53 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java                                                   |   13 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java                                             |  207 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ApplicationConfig.java                                          |   16 
 ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml                                                                |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java                                     |  127 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java                                                         |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java                                                |   76 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java                                       |  189 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ThreadPoolConfig.java                                           |   59 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java                                                 |   74 
 ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java                                                              |    0 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/SmsConfig.java                                                    |   48 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java                                                             |  104 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java                                      |   21 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java                                        |   90 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/PageQuery.java                                         |  114 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssFilter.java                                                    |   62 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessStatus.java                                                |   18 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaType.java                                                   |   29 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java                                                |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java                                        |  285 
 ruoyi-common/ruoyi-common-redis/pom.xml                                                                                                   |   38 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/MybatisExceptionHandler.java                              |   46 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java                                                   |   22 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/AddGroup.java                                                 |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaException.java                                   |   18 
 ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/MailConfig.java                                                 |   37 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/QueueUtils.java                                                |  180 
 ruoyi-modules/pom.xml                                                                                                                     |   27 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                                                             |    0 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/ResourcesConfig.java                                              |   52 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml                                                         |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java                                             |  118 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/XssValidator.java                                                  |   21 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/BigNumberSerializer.java                                       |   42 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java                                      |  137 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java                                                             |  131 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java                                                |  104 
 ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/listener/UserActionListener.java                                 |  139 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/CaptchaConfig.java                                                |   62 
 ruoyi-common/ruoyi-common-mail/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports        |    1 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java                                                     |   34 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/BaseEntity.java                                             |   65 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java                                                    |   13 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java                                           |   26 
 ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java                                              |  252 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java                                                    |  192 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/package-info.md                                                                      |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java                                              |   46 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/package-info.java                                                           |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java                                                    |  105 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java                                                 |    0 
 ruoyi-common/ruoyi-common-excel/pom.xml                                                                                                   |   31 
 ruoyi-common/ruoyi-common-satoken/pom.xml                                                                                                 |   39 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java                                                       |   31 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatableFilter.java                                             |   40 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java                                                |   38 
 ruoyi-modules/ruoyi-demo/src/main/resources/mapper/package-info.md                                                                        |    0 
 ruoyi-modules/ruoyi-demo/src/main/resources/excel/多列表.xlsx                                                                                |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordRetryLimitExceedException.java              |   19 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/config/MybatisPlusConfig.java                                    |  102 
 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java                            |  141 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefautExcelResult.java                                          |   73 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/R.java                                                          |  110 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/CellMerge.java                                            |   24 
 ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/enums/LimitType.java                                     |   24 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java                                                    |    0 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml                                                             |    0 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysRegisterController.java                                                             |    2 
 ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/annotation/DictDataMapper.java                                         |   27 
 ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/aspectj/RepeatSubmitAspect.java                            |  153 
 ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/annotation/RateLimiter.java                              |   36 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm                                                                            |    0 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java                                                           |   59 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/package-info.java                                                            |    0 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/exception/SmsException.java                                              |   19 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java                                                |  203 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/js/api.js.vm                                                                          |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java                                 |   88 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java                                       |   17 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataBaseHelper.java                                       |   72 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java                                             |   41 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java                                          |   52 
 ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/config/IdempotentConfig.java                               |   21 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java                                         |    0 
 ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports        |    7 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/JacksonConfig.java                                              |   47 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml                                                          |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Sensitive.java                                              |   24 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/manager/ShutdownManager.java                                           |   41 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/CellMergeStrategy.java                                          |  114 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java                                          |   24 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JsonUtils.java                                                   |  111 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/Xss.java                                                           |   26 
 ruoyi-common/ruoyi-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports         |    1 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/LogininforEvent.java                                               |   47 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatedlyRequestWrapper.java                                     |   67 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssConfigMapper.xml                                                        |    0 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/utils/ExcelUtil.java                                                 |  328 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataPermission.java                                   |   18 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java                    |   79 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java                                                 |   97 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java                                         |    0 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/SmsTemplate.java                                                    |   26 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java                                                     |   13 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysIndexController.java                                                                |    4 
 ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/annotation/RepeatSubmit.java                               |   29 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java                                                    |  211 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java                                       |   61 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java                                                        |  232 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java                                          |  106 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/UserConstants.java                                            |  138 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java                                                   |   13 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java                                             |   60 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StreamUtils.java                                                 |  251 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java                                            |  446 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java                                             |  161 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DictService.java                                               |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java                                                             |   83 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java                                          |  227 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java                                     |   40 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java                                                 |  106 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java                                                       |   62 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm                                                               |  117 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaSessionProcessor.java          |    0 
 ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/jackson/DictDataJsonSerializer.java                                    |   56 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java                                        |  130 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelDictConvert.java                                        |   73 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm                                                              |    0 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssMapper.xml                                                              |    0 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/TencentSmsTemplate.java                                             |   82 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/handler/KeyPrefixHandler.java                                        |   50 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm                                                                   |   15 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java                                        |  253 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java                                                  |   66 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/package-info.java                                                        |    0 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/bo.java.vm                                                                       |   60 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm                                                                 |    0 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm                                                                  |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/MimeTypeUtils.java                                          |   40 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java                                               |   47 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java                                                  |  148 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm                                                                       |   56 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/core/OssClient.java                                                      |  240 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/properties/SmsProperties.java                                     |   47 
 ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java                                                            |    0 
 ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/annotation/Log.java                                                      |   41 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java                                                         |   65 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java                                    |  116 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java                                            |  412 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java                                                |   58 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java                                                                 |   22 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ValidatorConfig.java                                            |   43 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java                                                           |   58 
 ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java                                                   |  336 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java                                             |   31 
 ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/UserPassAuthenticator.java                                       |   33 
 ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt                                                                     |    0 
 ruoyi-modules/ruoyi-job/pom.xml                                                                                                           |   36 
 ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/AliyunSmsTemplate.java                                              |   66 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java                                                       |   94 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java                                                 |  273 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataScopeType.java                                         |   72 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java                                               |   65 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java                                                           |   71 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java                                                       |   82 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/SensitiveStrategy.java                                           |   49 
 ruoyi-common/ruoyi-common-security/pom.xml                                                                                                |   33 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java                                                         |    0 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java                           |  199 
 ruoyi-common/ruoyi-common-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports         |    1 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/UndertowConfig.java                                               |   30 
 ruoyi-common/ruoyi-common-log/pom.xml                                                                                                     |   26 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/utils/UnsignedMathGenerator.java                                         |   88 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/TableDataInfo.java                                     |   81 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java                                            |   42 
 ruoyi-common/ruoyi-common-ratelimiter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |    1 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java                                             |  188 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java                     |   18 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java                                                                |   68 
 ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/config/properties/XxlJobProperties.java                                               |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java                                                          |  144 
 ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml                                                                            |   10 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelBigNumberConvert.java                                   |   52 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java                                                           |    0 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java                                                |   66 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java                                        |  237 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java                                        |  119 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java                                          |    0 
 ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/XssProperties.java                                     |   32 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java                                                  |    0 
 ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/mapper/BaseMapperPlus.java                                  |  192 
 ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java                                              |  130 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml                                                           |    0 
 ruoyi-modules/ruoyi-generator/src/main/resources/mapper/package-info.md                                                                   |    0 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BeanCopyUtils.java                                               |  204 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml                                                         |    0 
 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/AccessPolicyType.java                                              |   55 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java                                                       |   40 
 ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/ExcelDictFormat.java                                      |   30 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java                                                    |  179 
 ruoyi-admin/pom.xml                                                                                                                       |   22 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java                                                      |   52 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java                                                            |   47 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java                                                    |    0 
 ruoyi-common/pom.xml                                                                                                                      |  163 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java                                                     |   13 
 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/properties/SecurityProperties.java                      |   23 
 /dev/null                                                                                                                                 |  488 -
 ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/aspectj/RateLimiterAspect.java                           |   64 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java                                        |   67 
 ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java                                           |  135 
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/sql/SqlUtil.java                                                 |   57 
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml                                                           |    0 
 ruoyi-common/ruoyi-common-idempotent/pom.xml                                                                                              |   42 
 ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java                                                       |   71 
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java                                                   |   24 
 396 files changed, 26,201 insertions(+), 716 deletions(-)

diff --git a/pom.xml b/pom.xml
index fd9fdbd..0c0c775 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,15 @@
                 <scope>import</scope>
             </dependency>
 
+            <!-- common 鐨勪緷璧栭厤缃�-->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-bom</artifactId>
+                <version>${revision}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
             <dependency>
                 <groupId>org.springdoc</groupId>
                 <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
@@ -171,6 +180,11 @@
                     </exclusion>
                 </exclusions>
             </dependency>
+            <dependency>
+                <groupId>cn.dev33</groupId>
+                <artifactId>sa-token-core</artifactId>
+                <version>${satoken.version}</version>
+            </dependency>
 
             <!-- dynamic-datasource 澶氭暟鎹簮-->
             <dependency>
@@ -188,6 +202,12 @@
             <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-annotation</artifactId>
                 <version>${mybatis-plus.version}</version>
             </dependency>
 
@@ -265,77 +285,14 @@
                 <artifactId>snakeyaml</artifactId>
                 <version>${snakeyaml.version}</version>
             </dependency>
-
-            <!-- 瀹氭椂浠诲姟 -->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-job</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- 浠g爜鐢熸垚-->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-generator</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- 鏍稿績妯″潡-->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-framework</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- 绯荤粺妯″潡-->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-system</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- 閫氱敤宸ュ叿-->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-common</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- OSS瀵硅薄瀛樺偍妯″潡 -->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-oss</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- SMS鐭俊妯″潡 -->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-sms</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
-            <!-- demo妯″潡 -->
-            <dependency>
-                <groupId>com.ruoyi</groupId>
-                <artifactId>ruoyi-demo</artifactId>
-                <version>${revision}</version>
-            </dependency>
-
         </dependencies>
     </dependencyManagement>
 
     <modules>
         <module>ruoyi-admin</module>
-        <module>ruoyi-framework</module>
-        <module>ruoyi-system</module>
-        <module>ruoyi-job</module>
-        <module>ruoyi-generator</module>
         <module>ruoyi-common</module>
-        <module>ruoyi-demo</module>
         <module>ruoyi-extend</module>
-        <module>ruoyi-oss</module>
-        <module>ruoyi-sms</module>
+        <module>ruoyi-modules</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index e538024..fd1d0be 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -46,15 +46,24 @@
             <artifactId>mssql-jdbc</artifactId>
         </dependency>
 
-        <!-- 鏍稿績妯″潡-->
         <dependency>
             <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-framework</artifactId>
+            <artifactId>ruoyi-system</artifactId>
         </dependency>
 
         <dependency>
             <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-system</artifactId>
+            <artifactId>ruoyi-common-doc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-satoken</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-web</artifactId>
         </dependency>
 
         <dependency>
@@ -64,7 +73,12 @@
 
         <dependency>
             <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-oss</artifactId>
+            <artifactId>ruoyi-common-log</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-oss</artifactId>
         </dependency>
 
         <!-- 浠g爜鐢熸垚-->
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
index 554b7ea..f24a863 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/CaptchaController.java
@@ -5,18 +5,18 @@
 import cn.hutool.captcha.generator.CodeGenerator;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.RandomUtil;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.Constants;
 import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.enums.CaptchaType;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.common.utils.reflect.ReflectUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.framework.config.properties.CaptchaProperties;
-import com.ruoyi.sms.config.properties.SmsProperties;
-import com.ruoyi.sms.core.SmsTemplate;
-import com.ruoyi.sms.entity.SmsResult;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.reflect.ReflectUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.sms.config.properties.SmsProperties;
+import com.ruoyi.common.sms.core.SmsTemplate;
+import com.ruoyi.common.sms.entity.SmsResult;
+import com.ruoyi.common.web.config.properties.CaptchaProperties;
+import com.ruoyi.common.web.enums.CaptchaType;
 import com.ruoyi.system.service.ISysConfigService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysIndexController.java
index 3f3848f..368dbaf 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysIndexController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysIndexController.java
@@ -1,8 +1,8 @@
 package com.ruoyi.web.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
-import com.ruoyi.common.config.RuoYiConfig;
-import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.core.config.RuoYiConfig;
+import com.ruoyi.common.core.utils.StringUtils;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysLoginController.java
index eb98bf1..121d8b8 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysLoginController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysLoginController.java
@@ -1,14 +1,14 @@
 package com.ruoyi.web.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
-import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.constant.Constants;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.satoken.utils.LoginHelper;
 import com.ruoyi.system.domain.SysMenu;
 import com.ruoyi.system.domain.SysUser;
 import com.ruoyi.common.core.domain.model.LoginBody;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.core.domain.model.SmsLoginBody;
-import com.ruoyi.common.helper.LoginHelper;
 import com.ruoyi.system.domain.vo.RouterVo;
 import com.ruoyi.system.service.ISysMenuService;
 import com.ruoyi.system.service.ISysUserService;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysRegisterController.java
index b00bfd4..0973e3b 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysRegisterController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/SysRegisterController.java
@@ -1,7 +1,7 @@
 package com.ruoyi.web.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
-import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.web.controller.BaseController;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.domain.model.RegisterBody;
 import com.ruoyi.system.service.ISysConfigService;
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
index a40fd82..b40c123 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java
@@ -1,6 +1,6 @@
 package com.ruoyi.test;
 
-import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.config.RuoYiConfig;
 import org.junit.jupiter.api.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
index 04bf1b5..9d61383 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java
@@ -1,6 +1,6 @@
 package com.ruoyi.test;
 
-import com.ruoyi.common.enums.UserType;
+import com.ruoyi.common.core.enums.UserType;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index bc48fbe..1bb05e2 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -10,151 +10,30 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
+    <modules>
+        <module>ruoyi-common-bom</module>
+        <module>ruoyi-common-core</module>
+        <module>ruoyi-common-dict</module>
+        <module>ruoyi-common-doc</module>
+        <module>ruoyi-common-excel</module>
+        <module>ruoyi-common-idempotent</module>
+        <module>ruoyi-common-log</module>
+        <module>ruoyi-common-mail</module>
+        <module>ruoyi-common-mybatis</module>
+        <module>ruoyi-common-oss</module>
+        <module>ruoyi-common-ratelimiter</module>
+        <module>ruoyi-common-redis</module>
+        <module>ruoyi-common-satoken</module>
+        <module>ruoyi-common-security</module>
+        <module>ruoyi-common-sms</module>
+        <module>ruoyi-common-web</module>
+    </modules>
+
     <artifactId>ruoyi-common</artifactId>
+    <packaging>pom</packaging>
 
     <description>
-        common閫氱敤宸ュ叿
+        common 閫氱敤妯″潡
     </description>
-
-    <dependencies>
-
-        <!-- Spring妗嗘灦鍩烘湰鐨勬牳蹇冨伐鍏� -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-context-support</artifactId>
-        </dependency>
-
-        <!-- SpringWeb妯″潡 -->
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-        </dependency>
-
-        <!-- Sa-Token 鏉冮檺璁よ瘉, 鍦ㄧ嚎鏂囨。锛歨ttp://sa-token.dev33.cn/ -->
-        <dependency>
-            <groupId>cn.dev33</groupId>
-            <artifactId>sa-token-spring-boot3-starter</artifactId>
-        </dependency>
-        <!-- Sa-Token 鏁村悎 jwt -->
-        <dependency>
-            <groupId>cn.dev33</groupId>
-            <artifactId>sa-token-jwt</artifactId>
-        </dependency>
-
-        <!-- 鑷畾涔夐獙璇佹敞瑙� -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-validation</artifactId>
-        </dependency>
-
-        <!--甯哥敤宸ュ叿绫� -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-
-        <!-- JSON宸ュ叿绫� -->
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>easyexcel</artifactId>
-        </dependency>
-
-        <!-- yml瑙f瀽鍣� -->
-        <dependency>
-            <groupId>org.yaml</groupId>
-            <artifactId>snakeyaml</artifactId>
-        </dependency>
-
-        <!-- servlet鍖� -->
-        <dependency>
-            <groupId>jakarta.servlet</groupId>
-            <artifactId>jakarta.servlet-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>mybatis-plus-boot-starter</artifactId>
-        </dependency>
-
-        <!-- dynamic-datasource 澶氭暟鎹簮-->
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-http</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-captcha</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-jwt</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-extra</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>jakarta.mail</groupId>
-            <artifactId>jakarta.mail-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.github.therapi</groupId>
-            <artifactId>therapi-runtime-javadoc</artifactId>
-        </dependency>
-
-        <!--redisson-->
-        <dependency>
-            <groupId>org.redisson</groupId>
-            <artifactId>redisson-spring-boot-starter</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
-        </dependency>
-
-        <!--  鑷姩鐢熸垚YML閰嶇疆鍏宠仈JSON鏂囦欢  -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-properties-migrator</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-
-    </dependencies>
 
 </project>
diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml
new file mode 100644
index 0000000..ef00169
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-bom/pom.xml
@@ -0,0 +1,129 @@
+<?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>
+
+    <groupId>com.ruoyi</groupId>
+    <artifactId>ruoyi-common-bom</artifactId>
+    <version>${revision}</version>
+    <packaging>pom</packaging>
+
+    <description>
+        ruoyi-common-bom common渚濊禆椤�
+    </description>
+
+    <properties>
+        <revision>5.0.0-SNAPSHOT</revision>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <!-- 鏍稿績妯″潡 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-core</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 瀛楀吀 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-dict</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 鎺ュ彛妯″潡 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-doc</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- excel -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-excel</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 骞傜瓑 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-idempotent</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 鏃ュ織璁板綍 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-log</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 閭欢鏈嶅姟 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-mail</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 鏁版嵁搴撴湇鍔� -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-mybatis</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- OSS -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-oss</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 闄愭祦 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-ratelimiter</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 缂撳瓨鏈嶅姟 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-redis</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- satoken -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-satoken</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 瀹夊叏妯″潡 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-security</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- 鐭俊妯″潡 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-sms</artifactId>
+                <version>${revision}</version>
+            </dependency>
+
+            <!-- web鏈嶅姟 -->
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-web</artifactId>
+                <version>${revision}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml
new file mode 100644
index 0000000..8311af0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/pom.xml
@@ -0,0 +1,115 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-core</artifactId>
+
+    <description>
+        ruoyi-common-core 鏍稿績妯″潡
+    </description>
+
+    <dependencies>
+        <!-- Spring妗嗘灦鍩烘湰鐨勬牳蹇冨伐鍏� -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
+        <!-- SpringWeb妯″潡 -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-annotation</artifactId>
+        </dependency>
+
+        <!-- 鑷畾涔夐獙璇佹敞瑙� -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!--甯哥敤宸ュ叿绫� -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+
+        <!-- JSON宸ュ叿绫� -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
+
+        <!-- yml瑙f瀽鍣� -->
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
+
+        <!-- servlet鍖� -->
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-http</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-captcha</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-jwt</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-extra</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <!--  鑷姩鐢熸垚YML閰嶇疆鍏宠仈JSON鏂囦欢  -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-properties-migrator</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Sensitive.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Sensitive.java
new file mode 100644
index 0000000..0b2fbc1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Sensitive.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.core.annotation;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.core.enums.SensitiveStrategy;
+import com.ruoyi.common.core.jackson.SensitiveJsonSerializer;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鏁版嵁鑴辨晱娉ㄨВ
+ *
+ * @author zhujie
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@JacksonAnnotationsInside
+@JsonSerialize(using = SensitiveJsonSerializer.class)
+public @interface Sensitive {
+    SensitiveStrategy strategy();
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ApplicationConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ApplicationConfig.java
new file mode 100644
index 0000000..ef741a0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ApplicationConfig.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.core.config;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * 绋嬪簭娉ㄨВ閰嶇疆
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+// 琛ㄧず閫氳繃aop妗嗘灦鏆撮湶璇ヤ唬鐞嗗璞�,AopContext鑳藉璁块棶
+@EnableAspectJAutoProxy(exposeProxy = true)
+public class ApplicationConfig {
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java
new file mode 100644
index 0000000..5ed58f4
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/AsyncConfig.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.core.config;
+
+import cn.hutool.core.util.ArrayUtil;
+import com.ruoyi.common.core.exception.ServiceException;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.Arrays;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * 寮傛閰嶇疆
+ *
+ * @author Lion Li
+ */
+@EnableAsync(proxyTargetClass = true)
+@AutoConfiguration
+public class AsyncConfig implements AsyncConfigurer {
+
+    @Autowired
+    @Qualifier("scheduledExecutorService")
+    private ScheduledExecutorService scheduledExecutorService;
+
+    /**
+     * 鑷畾涔� @Async 娉ㄨВ浣跨敤绯荤粺绾跨▼姹�
+     */
+    @Override
+    public Executor getAsyncExecutor() {
+        return scheduledExecutorService;
+    }
+
+    /**
+     * 寮傛鎵ц寮傚父澶勭悊
+     */
+    @Override
+    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+        return (throwable, method, objects) -> {
+            throwable.printStackTrace();
+            StringBuilder sb = new StringBuilder();
+            sb.append("Exception message - ").append(throwable.getMessage())
+                .append(", Method name - ").append(method.getName());
+            if (ArrayUtil.isNotEmpty(objects)) {
+                sb.append(", Parameter value - ").append(Arrays.toString(objects));
+            }
+            throw new ServiceException(sb.toString());
+        };
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/JacksonConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/JacksonConfig.java
new file mode 100644
index 0000000..1a8c90b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/JacksonConfig.java
@@ -0,0 +1,47 @@
+package com.ruoyi.common.core.config;
+
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.ruoyi.common.core.jackson.BigNumberSerializer;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.TimeZone;
+
+/**
+ * jackson 閰嶇疆
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@AutoConfiguration(before = JacksonAutoConfiguration.class)
+public class JacksonConfig {
+
+    @Bean
+    public Jackson2ObjectMapperBuilderCustomizer customizer() {
+        return builder -> {
+            // 鍏ㄥ眬閰嶇疆搴忓垪鍖栬繑鍥� JSON 澶勭悊
+            JavaTimeModule javaTimeModule = new JavaTimeModule();
+            javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
+            javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
+            javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
+            javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
+            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
+            builder.modules(javaTimeModule);
+            builder.timeZone(TimeZone.getDefault());
+            log.info("鍒濆鍖� jackson 閰嶇疆");
+        };
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/RuoYiConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/RuoYiConfig.java
new file mode 100644
index 0000000..6185fbc
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/RuoYiConfig.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.core.config;
+
+import lombok.Data;
+import lombok.Getter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 璇诲彇椤圭洰鐩稿叧閰嶇疆
+ *
+ * @author Lion Li
+ */
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "ruoyi")
+public class RuoYiConfig {
+
+    /**
+     * 椤圭洰鍚嶇О
+     */
+    private String name;
+
+    /**
+     * 鐗堟湰
+     */
+    private String version;
+
+    /**
+     * 鐗堟潈骞翠唤
+     */
+    private String copyrightYear;
+
+    /**
+     * 瀹炰緥婕旂ず寮�鍏�
+     */
+    private boolean demoEnabled;
+
+    /**
+     * 缂撳瓨鎳掑姞杞�
+     */
+    private boolean cacheLazy;
+
+    /**
+     * 鑾峰彇鍦板潃寮�鍏�
+     */
+    @Getter
+    private static boolean addressEnabled;
+
+    public void setAddressEnabled(boolean addressEnabled) {
+        RuoYiConfig.addressEnabled = addressEnabled;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ThreadPoolConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ThreadPoolConfig.java
new file mode 100644
index 0000000..b829ac8
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ThreadPoolConfig.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.core.config;
+
+import com.ruoyi.common.core.config.properties.ThreadPoolProperties;
+import com.ruoyi.common.core.utils.Threads;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 绾跨▼姹犻厤缃�
+ *
+ * @author Lion Li
+ **/
+@AutoConfiguration
+public class ThreadPoolConfig {
+
+    /**
+     * 鏍稿績绾跨▼鏁� = cpu 鏍稿績鏁� + 1
+     */
+    private final int core = Runtime.getRuntime().availableProcessors() + 1;
+
+    @Autowired
+    private ThreadPoolProperties threadPoolProperties;
+
+    @Bean(name = "threadPoolTaskExecutor")
+    @ConditionalOnProperty(prefix = "thread-pool", name = "enabled", havingValue = "true")
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(core);
+        executor.setMaxPoolSize(core * 2);
+        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
+        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        return executor;
+    }
+
+    /**
+     * 鎵ц鍛ㄦ湡鎬ф垨瀹氭椂浠诲姟
+     */
+    @Bean(name = "scheduledExecutorService")
+    protected ScheduledExecutorService scheduledExecutorService() {
+        return new ScheduledThreadPoolExecutor(core,
+            new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
+            new ThreadPoolExecutor.CallerRunsPolicy()) {
+            @Override
+            protected void afterExecute(Runnable r, Throwable t) {
+                super.afterExecute(r, t);
+                Threads.printException(r, t);
+            }
+        };
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ValidatorConfig.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ValidatorConfig.java
new file mode 100644
index 0000000..da3fc8b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/ValidatorConfig.java
@@ -0,0 +1,43 @@
+package com.ruoyi.common.core.config;
+
+import org.hibernate.validator.HibernateValidator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.MessageSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+
+import jakarta.validation.Validator;
+import java.util.Properties;
+
+/**
+ * 鏍¢獙妗嗘灦閰嶇疆绫�
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+public class ValidatorConfig {
+
+    @Autowired
+    private MessageSource messageSource;
+
+    /**
+     * 閰嶇疆鏍¢獙妗嗘灦 蹇�熻繑鍥炴ā寮�
+     */
+    @Bean
+    public Validator validator() {
+        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
+        // 鍥介檯鍖�
+        factoryBean.setValidationMessageSource(messageSource);
+        // 璁剧疆浣跨敤 HibernateValidator 鏍¢獙鍣�
+        factoryBean.setProviderClass(HibernateValidator.class);
+        Properties properties = new Properties();
+        // 璁剧疆 蹇�熷紓甯歌繑鍥�
+        properties.setProperty("hibernate.validator.fail_fast", "true");
+        factoryBean.setValidationProperties(properties);
+        // 鍔犺浇閰嶇疆
+        factoryBean.afterPropertiesSet();
+        return factoryBean.getValidator();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/properties/ThreadPoolProperties.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/properties/ThreadPoolProperties.java
new file mode 100644
index 0000000..d967ad3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/config/properties/ThreadPoolProperties.java
@@ -0,0 +1,32 @@
+package com.ruoyi.common.core.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 绾跨▼姹� 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "thread-pool")
+public class ThreadPoolProperties {
+
+    /**
+     * 鏄惁寮�鍚嚎绋嬫睜
+     */
+    private boolean enabled;
+
+    /**
+     * 闃熷垪鏈�澶ч暱搴�
+     */
+    private int queueCapacity;
+
+    /**
+     * 绾跨▼姹犵淮鎶ょ嚎绋嬫墍鍏佽鐨勭┖闂叉椂闂�
+     */
+    private int keepAliveSeconds;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
new file mode 100644
index 0000000..38a31ee
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 缂撳瓨鐨刱ey 甯搁噺
+ *
+ * @author ruoyi
+ */
+public interface CacheConstants {
+
+    /**
+     * 鐧诲綍鐢ㄦ埛 redis key
+     */
+    String LOGIN_TOKEN_KEY = "Authorization:login:token:";
+
+    /**
+     * 鍦ㄧ嚎鐢ㄦ埛 redis key
+     */
+    String ONLINE_TOKEN_KEY = "online_tokens:";
+
+    /**
+     * 楠岃瘉鐮� redis key
+     */
+    String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 鍙傛暟绠$悊 cache key
+     */
+    String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 瀛楀吀绠$悊 cache key
+     */
+    String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 闃查噸鎻愪氦 redis key
+     */
+    String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+    /**
+     * 闄愭祦 redis key
+     */
+    String RATE_LIMIT_KEY = "rate_limit:";
+
+    /**
+     * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟 redis key
+     */
+    String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheNames.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheNames.java
new file mode 100644
index 0000000..ba09e9c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheNames.java
@@ -0,0 +1,48 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 缂撳瓨缁勫悕绉板父閲�
+ * <p>
+ * key 鏍煎紡涓� cacheNames#ttl#maxIdleTime#maxSize
+ * <p>
+ * ttl 杩囨湡鏃堕棿 濡傛灉璁剧疆涓�0鍒欎笉杩囨湡 榛樿涓�0
+ * maxIdleTime 鏈�澶х┖闂叉椂闂� 鏍规嵁LRU绠楁硶娓呯悊绌洪棽鏁版嵁 濡傛灉璁剧疆涓�0鍒欎笉妫�娴� 榛樿涓�0
+ * maxSize 缁勬渶澶ч暱搴� 鏍规嵁LRU绠楁硶娓呯悊婧㈠嚭鏁版嵁 濡傛灉璁剧疆涓�0鍒欐棤闄愰暱 榛樿涓�0
+ * <p>
+ * 渚嬪瓙: test#60s銆乼est#0#60s銆乼est#0#1m#1000銆乼est#1h#0#500
+ *
+ * @author Lion Li
+ */
+public interface CacheNames {
+
+    /**
+     * 婕旂ず妗堜緥
+     */
+    String DEMO_CACHE = "demo:cache#60s#10m#20";
+
+    /**
+     * 绯荤粺閰嶇疆
+     */
+    String SYS_CONFIG = "sys_config";
+
+    /**
+     * 鏁版嵁瀛楀吀
+     */
+    String SYS_DICT = "sys_dict";
+
+    /**
+     * OSS鍐呭
+     */
+    String SYS_OSS = "sys_oss#30d";
+
+    /**
+     * OSS閰嶇疆
+     */
+    String SYS_OSS_CONFIG = "sys_oss_config";
+
+    /**
+     * 鍦ㄧ嚎鐢ㄦ埛
+     */
+    String ONLINE_TOKEN = "online_tokens";
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
new file mode 100644
index 0000000..155d0dc
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java
@@ -0,0 +1,76 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 閫氱敤甯搁噺淇℃伅
+ *
+ * @author ruoyi
+ */
+public interface Constants {
+
+    /**
+     * UTF-8 瀛楃闆�
+     */
+    String UTF8 = "UTF-8";
+
+    /**
+     * GBK 瀛楃闆�
+     */
+    String GBK = "GBK";
+
+    /**
+     * www涓诲煙
+     */
+    String WWW = "www.";
+
+    /**
+     * http璇锋眰
+     */
+    String HTTP = "http://";
+
+    /**
+     * https璇锋眰
+     */
+    String HTTPS = "https://";
+
+    /**
+     * 閫氱敤鎴愬姛鏍囪瘑
+     */
+    String SUCCESS = "0";
+
+    /**
+     * 閫氱敤澶辫触鏍囪瘑
+     */
+    String FAIL = "1";
+
+    /**
+     * 鐧诲綍鎴愬姛
+     */
+    String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 娉ㄩ攢
+     */
+    String LOGOUT = "Logout";
+
+    /**
+     * 娉ㄥ唽
+     */
+    String REGISTER = "Register";
+
+    /**
+     * 鐧诲綍澶辫触
+     */
+    String LOGIN_FAIL = "Error";
+
+    /**
+     * 楠岃瘉鐮佹湁鏁堟湡锛堝垎閽燂級
+     */
+    Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 浠ょ墝
+     */
+    String TOKEN = "token";
+
+}
+
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java
new file mode 100644
index 0000000..aa1795b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/GenConstants.java
@@ -0,0 +1,188 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 浠g爜鐢熸垚閫氱敤甯搁噺
+ *
+ * @author ruoyi
+ */
+public interface GenConstants {
+    /**
+     * 鍗曡〃锛堝鍒犳敼鏌ワ級
+     */
+    String TPL_CRUD = "crud";
+
+    /**
+     * 鏍戣〃锛堝鍒犳敼鏌ワ級
+     */
+    String TPL_TREE = "tree";
+
+    /**
+     * 鏍戠紪鐮佸瓧娈�
+     */
+    String TREE_CODE = "treeCode";
+
+    /**
+     * 鏍戠埗缂栫爜瀛楁
+     */
+    String TREE_PARENT_CODE = "treeParentCode";
+
+    /**
+     * 鏍戝悕绉板瓧娈�
+     */
+    String TREE_NAME = "treeName";
+
+    /**
+     * 涓婄骇鑿滃崟ID瀛楁
+     */
+    String PARENT_MENU_ID = "parentMenuId";
+
+    /**
+     * 涓婄骇鑿滃崟鍚嶇О瀛楁
+     */
+    String PARENT_MENU_NAME = "parentMenuName";
+
+    /**
+     * 鏁版嵁搴撳瓧绗︿覆绫诲瀷
+     */
+    String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
+
+    /**
+     * 鏁版嵁搴撴枃鏈被鍨�
+     */
+    String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
+
+    /**
+     * 鏁版嵁搴撴椂闂寸被鍨�
+     */
+    String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
+
+    /**
+     * 鏁版嵁搴撴暟瀛楃被鍨�
+     */
+    String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
+        "bit", "bigint", "float", "double", "decimal"};
+
+    /**
+     * BO瀵硅薄 涓嶉渶瑕佹坊鍔犲瓧娈�
+     */
+    String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time", "del_flag", "update_by",
+        "update_time", "version"};
+
+    /**
+     * BO瀵硅薄 涓嶉渶瑕佺紪杈戝瓧娈�
+     */
+    String[] COLUMNNAME_NOT_EDIT = {"create_by", "create_time", "del_flag", "update_by",
+        "update_time", "version"};
+
+    /**
+     * VO瀵硅薄 涓嶉渶瑕佽繑鍥炲瓧娈�
+     */
+    String[] COLUMNNAME_NOT_LIST = {"create_by", "create_time", "del_flag", "update_by",
+        "update_time", "version"};
+
+    /**
+     * BO瀵硅薄 涓嶉渶瑕佹煡璇㈠瓧娈�
+     */
+    String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
+        "update_time", "remark", "version"};
+
+    /**
+     * Entity鍩虹被瀛楁
+     */
+    String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime"};
+
+    /**
+     * Tree鍩虹被瀛楁
+     */
+    String[] TREE_ENTITY = {"parentName", "parentId", "children"};
+
+    /**
+     * 鏂囨湰妗�
+     */
+    String HTML_INPUT = "input";
+
+    /**
+     * 鏂囨湰鍩�
+     */
+    String HTML_TEXTAREA = "textarea";
+
+    /**
+     * 涓嬫媺妗�
+     */
+    String HTML_SELECT = "select";
+
+    /**
+     * 鍗曢�夋
+     */
+    String HTML_RADIO = "radio";
+
+    /**
+     * 澶嶉�夋
+     */
+    String HTML_CHECKBOX = "checkbox";
+
+    /**
+     * 鏃ユ湡鎺т欢
+     */
+    String HTML_DATETIME = "datetime";
+
+    /**
+     * 鍥剧墖涓婁紶鎺т欢
+     */
+    String HTML_IMAGE_UPLOAD = "imageUpload";
+
+    /**
+     * 鏂囦欢涓婁紶鎺т欢
+     */
+    String HTML_FILE_UPLOAD = "fileUpload";
+
+    /**
+     * 瀵屾枃鏈帶浠�
+     */
+    String HTML_EDITOR = "editor";
+
+    /**
+     * 瀛楃涓茬被鍨�
+     */
+    String TYPE_STRING = "String";
+
+    /**
+     * 鏁村瀷
+     */
+    String TYPE_INTEGER = "Integer";
+
+    /**
+     * 闀挎暣鍨�
+     */
+    String TYPE_LONG = "Long";
+
+    /**
+     * 娴偣鍨�
+     */
+    String TYPE_DOUBLE = "Double";
+
+    /**
+     * 楂樼簿搴﹁绠楃被鍨�
+     */
+    String TYPE_BIGDECIMAL = "BigDecimal";
+
+    /**
+     * 鏃堕棿绫诲瀷
+     */
+    String TYPE_DATE = "Date";
+
+    /**
+     * 妯$硦鏌ヨ
+     */
+    String QUERY_LIKE = "LIKE";
+
+    /**
+     * 鐩哥瓑鏌ヨ
+     */
+    String QUERY_EQ = "EQ";
+
+    /**
+     * 闇�瑕�
+     */
+    String REQUIRE = "1";
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HttpStatus.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HttpStatus.java
new file mode 100644
index 0000000..d19931a
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HttpStatus.java
@@ -0,0 +1,93 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 杩斿洖鐘舵�佺爜
+ *
+ * @author Lion Li
+ */
+public interface HttpStatus {
+    /**
+     * 鎿嶄綔鎴愬姛
+     */
+    int SUCCESS = 200;
+
+    /**
+     * 瀵硅薄鍒涘缓鎴愬姛
+     */
+    int CREATED = 201;
+
+    /**
+     * 璇锋眰宸茬粡琚帴鍙�
+     */
+    int ACCEPTED = 202;
+
+    /**
+     * 鎿嶄綔宸茬粡鎵ц鎴愬姛锛屼絾鏄病鏈夎繑鍥炴暟鎹�
+     */
+    int NO_CONTENT = 204;
+
+    /**
+     * 璧勬簮宸茶绉婚櫎
+     */
+    int MOVED_PERM = 301;
+
+    /**
+     * 閲嶅畾鍚�
+     */
+    int SEE_OTHER = 303;
+
+    /**
+     * 璧勬簮娌℃湁琚慨鏀�
+     */
+    int NOT_MODIFIED = 304;
+
+    /**
+     * 鍙傛暟鍒楄〃閿欒锛堢己灏戯紝鏍煎紡涓嶅尮閰嶏級
+     */
+    int BAD_REQUEST = 400;
+
+    /**
+     * 鏈巿鏉�
+     */
+    int UNAUTHORIZED = 401;
+
+    /**
+     * 璁块棶鍙楅檺锛屾巿鏉冭繃鏈�
+     */
+    int FORBIDDEN = 403;
+
+    /**
+     * 璧勬簮锛屾湇鍔℃湭鎵惧埌
+     */
+    int NOT_FOUND = 404;
+
+    /**
+     * 涓嶅厑璁哥殑http鏂规硶
+     */
+    int BAD_METHOD = 405;
+
+    /**
+     * 璧勬簮鍐茬獊锛屾垨鑰呰祫婧愯閿�
+     */
+    int CONFLICT = 409;
+
+    /**
+     * 涓嶆敮鎸佺殑鏁版嵁锛屽獟浣撶被鍨�
+     */
+    int UNSUPPORTED_TYPE = 415;
+
+    /**
+     * 绯荤粺鍐呴儴閿欒
+     */
+    int ERROR = 500;
+
+    /**
+     * 鎺ュ彛鏈疄鐜�
+     */
+    int NOT_IMPLEMENTED = 501;
+
+    /**
+     * 绯荤粺璀﹀憡娑堟伅
+     */
+    int WARN = 601;
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/UserConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/UserConstants.java
new file mode 100644
index 0000000..4a73c08
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/UserConstants.java
@@ -0,0 +1,138 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 鐢ㄦ埛甯搁噺淇℃伅
+ *
+ * @author ruoyi
+ */
+public interface UserConstants {
+
+    /**
+     * 骞冲彴鍐呯郴缁熺敤鎴风殑鍞竴鏍囧織
+     */
+    String SYS_USER = "SYS_USER";
+
+    /**
+     * 姝e父鐘舵��
+     */
+    String NORMAL = "0";
+
+    /**
+     * 寮傚父鐘舵��
+     */
+    String EXCEPTION = "1";
+
+    /**
+     * 鐢ㄦ埛姝e父鐘舵��
+     */
+    String USER_NORMAL = "0";
+
+    /**
+     * 鐢ㄦ埛灏佺鐘舵��
+     */
+    String USER_DISABLE = "1";
+
+    /**
+     * 瑙掕壊姝e父鐘舵��
+     */
+    String ROLE_NORMAL = "0";
+
+    /**
+     * 瑙掕壊灏佺鐘舵��
+     */
+    String ROLE_DISABLE = "1";
+
+    /**
+     * 閮ㄩ棬姝e父鐘舵��
+     */
+    String DEPT_NORMAL = "0";
+
+    /**
+     * 閮ㄩ棬鍋滅敤鐘舵��
+     */
+    String DEPT_DISABLE = "1";
+
+    /**
+     * 瀛楀吀姝e父鐘舵��
+     */
+    String DICT_NORMAL = "0";
+
+    /**
+     * 鏄惁涓虹郴缁熼粯璁わ紙鏄級
+     */
+    String YES = "Y";
+
+    /**
+     * 鏄惁鑿滃崟澶栭摼锛堟槸锛�
+     */
+    String YES_FRAME = "0";
+
+    /**
+     * 鏄惁鑿滃崟澶栭摼锛堝惁锛�
+     */
+    String NO_FRAME = "1";
+
+    /**
+     * 鑿滃崟姝e父鐘舵��
+     */
+    String MENU_NORMAL = "0";
+
+    /**
+     * 鑿滃崟鍋滅敤鐘舵��
+     */
+    String MENU_DISABLE = "1";
+
+    /**
+     * 鑿滃崟绫诲瀷锛堢洰褰曪級
+     */
+    String TYPE_DIR = "M";
+
+    /**
+     * 鑿滃崟绫诲瀷锛堣彍鍗曪級
+     */
+    String TYPE_MENU = "C";
+
+    /**
+     * 鑿滃崟绫诲瀷锛堟寜閽級
+     */
+    String TYPE_BUTTON = "F";
+
+    /**
+     * Layout缁勪欢鏍囪瘑
+     */
+    String LAYOUT = "Layout";
+
+    /**
+     * ParentView缁勪欢鏍囪瘑
+     */
+    String PARENT_VIEW = "ParentView";
+
+    /**
+     * InnerLink缁勪欢鏍囪瘑
+     */
+    String INNER_LINK = "InnerLink";
+
+    /**
+     * 鏍¢獙杩斿洖缁撴灉鐮�
+     */
+    String UNIQUE = "0";
+    String NOT_UNIQUE = "1";
+
+    /**
+     * 鐢ㄦ埛鍚嶉暱搴﹂檺鍒�
+     */
+    int USERNAME_MIN_LENGTH = 2;
+    int USERNAME_MAX_LENGTH = 20;
+
+    /**
+     * 瀵嗙爜闀垮害闄愬埗
+     */
+    int PASSWORD_MIN_LENGTH = 5;
+    int PASSWORD_MAX_LENGTH = 20;
+
+    /**
+     * 绠$悊鍛業D
+     */
+    Long ADMIN_ID = 1L;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/R.java
new file mode 100644
index 0000000..79b7941
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/R.java
@@ -0,0 +1,110 @@
+package com.ruoyi.common.core.domain;
+
+import com.ruoyi.common.core.constant.HttpStatus;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 鍝嶅簲淇℃伅涓讳綋
+ *
+ * @author Lion Li
+ */
+@Data
+@NoArgsConstructor
+public class R<T> implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鎴愬姛
+     */
+    public static final int SUCCESS = 200;
+
+    /**
+     * 澶辫触
+     */
+    public static final int FAIL = 500;
+
+    private int code;
+
+    private String msg;
+
+    private T data;
+
+    public static <T> R<T> ok() {
+        return restResult(null, SUCCESS, "鎿嶄綔鎴愬姛");
+    }
+
+    public static <T> R<T> ok(T data) {
+        return restResult(data, SUCCESS, "鎿嶄綔鎴愬姛");
+    }
+
+    public static <T> R<T> ok(String msg) {
+        return restResult(null, SUCCESS, msg);
+    }
+
+    public static <T> R<T> ok(String msg, T data) {
+        return restResult(data, SUCCESS, msg);
+    }
+
+    public static <T> R<T> fail() {
+        return restResult(null, FAIL, "鎿嶄綔澶辫触");
+    }
+
+    public static <T> R<T> fail(String msg) {
+        return restResult(null, FAIL, msg);
+    }
+
+    public static <T> R<T> fail(T data) {
+        return restResult(data, FAIL, "鎿嶄綔澶辫触");
+    }
+
+    public static <T> R<T> fail(String msg, T data) {
+        return restResult(data, FAIL, msg);
+    }
+
+    public static <T> R<T> fail(int code, String msg) {
+        return restResult(null, code, msg);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @return 璀﹀憡娑堟伅
+     */
+    public static <T> R<T> warn(String msg) {
+        return restResult(null, HttpStatus.WARN, msg);
+    }
+
+    /**
+     * 杩斿洖璀﹀憡娑堟伅
+     *
+     * @param msg 杩斿洖鍐呭
+     * @param data 鏁版嵁瀵硅薄
+     * @return 璀﹀憡娑堟伅
+     */
+    public static <T> R<T> warn(String msg, T data) {
+        return restResult(data, HttpStatus.WARN, msg);
+    }
+
+    private static <T> R<T> restResult(T data, int code, String msg) {
+        R<T> r = new R<>();
+        r.setCode(code);
+        r.setData(data);
+        r.setMsg(msg);
+        return r;
+    }
+
+    public static <T> Boolean isError(R<T> ret) {
+        return !isSuccess(ret);
+    }
+
+    public static <T> Boolean isSuccess(R<T> ret) {
+        return R.SUCCESS == ret.getCode();
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/RoleDTO.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/dto/UserOnlineDTO.java
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
new file mode 100644
index 0000000..eab6581
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
@@ -0,0 +1,42 @@
+package com.ruoyi.common.core.domain.model;
+
+import com.ruoyi.common.core.constant.UserConstants;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * 鐢ㄦ埛鐧诲綍瀵硅薄
+ *
+ * @author Lion Li
+ */
+
+@Data
+public class LoginBody {
+
+    /**
+     * 鐢ㄦ埛鍚�
+     */
+    @NotBlank(message = "{user.username.not.blank}")
+    @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
+    private String username;
+
+    /**
+     * 鐢ㄦ埛瀵嗙爜
+     */
+    @NotBlank(message = "{user.password.not.blank}")
+    @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
+    private String password;
+
+    /**
+     * 楠岃瘉鐮�
+     */
+    private String code;
+
+    /**
+     * 鍞竴鏍囪瘑
+     */
+    private String uuid;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
new file mode 100644
index 0000000..7db0464
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
@@ -0,0 +1,118 @@
+package com.ruoyi.common.core.domain.model;
+
+import com.ruoyi.common.core.domain.dto.RoleDTO;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 鐧诲綍鐢ㄦ埛韬唤鏉冮檺
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+public class LoginUser implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    private Long userId;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    private Long deptId;
+
+    /**
+     * 閮ㄩ棬鍚�
+     */
+    private String deptName;
+
+    /**
+     * 鐢ㄦ埛鍞竴鏍囪瘑
+     */
+    private String token;
+
+    /**
+     * 鐢ㄦ埛绫诲瀷
+     */
+    private String userType;
+
+    /**
+     * 鐧诲綍鏃堕棿
+     */
+    private Long loginTime;
+
+    /**
+     * 杩囨湡鏃堕棿
+     */
+    private Long expireTime;
+
+    /**
+     * 鐧诲綍IP鍦板潃
+     */
+    private String ipaddr;
+
+    /**
+     * 鐧诲綍鍦扮偣
+     */
+    private String loginLocation;
+
+    /**
+     * 娴忚鍣ㄧ被鍨�
+     */
+    private String browser;
+
+    /**
+     * 鎿嶄綔绯荤粺
+     */
+    private String os;
+
+    /**
+     * 鑿滃崟鏉冮檺
+     */
+    private Set<String> menuPermission;
+
+    /**
+     * 瑙掕壊鏉冮檺
+     */
+    private Set<String> rolePermission;
+
+    /**
+     * 鐢ㄦ埛鍚�
+     */
+    private String username;
+
+    /**
+     * 瑙掕壊瀵硅薄
+     */
+    private List<RoleDTO> roles;
+
+    /**
+     * 鏁版嵁鏉冮檺 褰撳墠瑙掕壊ID
+     */
+    private Long roleId;
+
+    /**
+     * 鑾峰彇鐧诲綍id
+     */
+    public String getLoginId() {
+        if (userType == null) {
+            throw new IllegalArgumentException("鐢ㄦ埛绫诲瀷涓嶈兘涓虹┖");
+        }
+        if (userId == null) {
+            throw new IllegalArgumentException("鐢ㄦ埛ID涓嶈兘涓虹┖");
+        }
+        return userType + ":" + userId;
+    }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java
new file mode 100644
index 0000000..b15b91c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceType.java
@@ -0,0 +1,32 @@
+package com.ruoyi.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 璁惧绫诲瀷
+ * 閽堝涓�濂� 鐢ㄦ埛浣撶郴
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum DeviceType {
+
+    /**
+     * pc绔�
+     */
+    PC("pc"),
+
+    /**
+     * app绔�
+     */
+    APP("app"),
+
+    /**
+     * 灏忕▼搴忕
+     */
+    XCX("xcx");
+
+    private final String device;
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/LoginType.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/LoginType.java
new file mode 100644
index 0000000..fcd48df
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/LoginType.java
@@ -0,0 +1,39 @@
+package com.ruoyi.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 鐧诲綍绫诲瀷
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum LoginType {
+
+    /**
+     * 瀵嗙爜鐧诲綍
+     */
+    PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"),
+
+    /**
+     * 鐭俊鐧诲綍
+     */
+    SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"),
+
+    /**
+     * 灏忕▼搴忕櫥褰�
+     */
+    XCX("", "");
+
+    /**
+     * 鐧诲綍閲嶈瘯瓒呭嚭闄愬埗鎻愮ず
+     */
+    final String retryLimitExceed;
+
+    /**
+     * 鐧诲綍閲嶈瘯闄愬埗璁℃暟鎻愮ず
+     */
+    final String retryLimitCount;
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/SensitiveStrategy.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/SensitiveStrategy.java
new file mode 100644
index 0000000..c58ea49
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/SensitiveStrategy.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.core.enums;
+
+import cn.hutool.core.util.DesensitizedUtil;
+import lombok.AllArgsConstructor;
+
+import java.util.function.Function;
+
+/**
+ * 鑴辨晱绛栫暐
+ *
+ * @author Yjoioooo
+ * @version 3.6.0
+ */
+@AllArgsConstructor
+public enum SensitiveStrategy {
+
+    /**
+     * 韬唤璇佽劚鏁�
+     */
+    ID_CARD(s -> DesensitizedUtil.idCardNum(s, 3, 4)),
+
+    /**
+     * 鎵嬫満鍙疯劚鏁�
+     */
+    PHONE(DesensitizedUtil::mobilePhone),
+
+    /**
+     * 鍦板潃鑴辨晱
+     */
+    ADDRESS(s -> DesensitizedUtil.address(s, 8)),
+
+    /**
+     * 閭鑴辨晱
+     */
+    EMAIL(DesensitizedUtil::email),
+
+    /**
+     * 閾惰鍗�
+     */
+    BANK_CARD(DesensitizedUtil::bankCard);
+
+    //鍙嚜琛屾坊鍔犲叾浠栬劚鏁忕瓥鐣�
+
+    private final Function<String, String> desensitizer;
+
+    public Function<String, String> desensitizer() {
+        return desensitizer;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java
new file mode 100644
index 0000000..b546f37
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserStatus.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.core.enums;
+
+/**
+ * 鐢ㄦ埛鐘舵��
+ *
+ * @author ruoyi
+ */
+public enum UserStatus {
+    OK("0", "姝e父"), DISABLE("1", "鍋滅敤"), DELETED("2", "鍒犻櫎");
+
+    private final String code;
+    private final String info;
+
+    UserStatus(String code, String info) {
+        this.code = code;
+        this.info = info;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getInfo() {
+        return info;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java
new file mode 100644
index 0000000..46e4005
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/UserType.java
@@ -0,0 +1,37 @@
+package com.ruoyi.common.core.enums;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 璁惧绫诲瀷
+ * 閽堝澶氬 鐢ㄦ埛浣撶郴
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum UserType {
+
+    /**
+     * pc绔�
+     */
+    SYS_USER("sys_user"),
+
+    /**
+     * app绔�
+     */
+    APP_USER("app_user");
+
+    private final String userType;
+
+    public static UserType getUserType(String str) {
+        for (UserType value : values()) {
+            if (StringUtils.contains(str, value.getUserType())) {
+                return value;
+            }
+        }
+        throw new RuntimeException("'UserType' not found By " + str);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java
new file mode 100644
index 0000000..7911e3c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/DemoModeException.java
@@ -0,0 +1,17 @@
+package com.ruoyi.common.core.exception;
+
+import java.io.Serial;
+
+/**
+ * 婕旂ず妯″紡寮傚父
+ *
+ * @author ruoyi
+ */
+public class DemoModeException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public DemoModeException() {
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java
new file mode 100644
index 0000000..464d983
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/GlobalException.java
@@ -0,0 +1,53 @@
+package com.ruoyi.common.core.exception;
+
+import java.io.Serial;
+
+/**
+ * 鍏ㄥ眬寮傚父
+ *
+ * @author ruoyi
+ */
+public class GlobalException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閿欒鎻愮ず
+     */
+    private String message;
+
+    /**
+     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+     */
+    private String detailMessage;
+
+    /**
+     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+     */
+    public GlobalException() {
+    }
+
+    public GlobalException(String message) {
+        this.message = message;
+    }
+
+    public String getDetailMessage() {
+        return detailMessage;
+    }
+
+    public GlobalException setDetailMessage(String detailMessage) {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public GlobalException setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
new file mode 100644
index 0000000..0ef0534
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.core.exception;
+
+import java.io.Serial;
+
+/**
+ * 涓氬姟寮傚父
+ *
+ * @author ruoyi
+ */
+public final class ServiceException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閿欒鐮�
+     */
+    private Integer code;
+
+    /**
+     * 閿欒鎻愮ず
+     */
+    private String message;
+
+    /**
+     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+     */
+    private String detailMessage;
+
+    /**
+     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+     */
+    public ServiceException() {
+    }
+
+    public ServiceException(String message) {
+        this.message = message;
+    }
+
+    public ServiceException(String message, Integer code) {
+        this.message = message;
+        this.code = code;
+    }
+
+    public String getDetailMessage() {
+        return detailMessage;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public ServiceException setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage) {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java
new file mode 100644
index 0000000..587ae7f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/UtilException.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.core.exception;
+
+import java.io.Serial;
+
+/**
+ * 宸ュ叿绫诲紓甯�
+ *
+ * @author ruoyi
+ */
+public class UtilException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 8247610319171014183L;
+
+    public UtilException(Throwable e) {
+        super(e.getMessage(), e);
+    }
+
+    public UtilException(String message) {
+        super(message);
+    }
+
+    public UtilException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
new file mode 100644
index 0000000..195e141
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/base/BaseException.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.core.exception.base;
+
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+
+/**
+ * 鍩虹寮傚父
+ *
+ * @author ruoyi
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class BaseException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鎵�灞炴ā鍧�
+     */
+    private String module;
+
+    /**
+     * 閿欒鐮�
+     */
+    private String code;
+
+    /**
+     * 閿欒鐮佸搴旂殑鍙傛暟
+     */
+    private Object[] args;
+
+    /**
+     * 閿欒娑堟伅
+     */
+    private String defaultMessage;
+
+    public BaseException(String module, String code, Object[] args, String defaultMessage) {
+        this.module = module;
+        this.code = code;
+        this.args = args;
+        this.defaultMessage = defaultMessage;
+    }
+
+    public BaseException(String module, String code, Object[] args) {
+        this(module, code, args, null);
+    }
+
+    public BaseException(String module, String defaultMessage) {
+        this(module, null, null, defaultMessage);
+    }
+
+    public BaseException(String code, Object[] args) {
+        this(null, code, args, null);
+    }
+
+    public BaseException(String defaultMessage) {
+        this(null, null, null, defaultMessage);
+    }
+
+    @Override
+    public String getMessage() {
+        String message = null;
+        if (!StringUtils.isEmpty(code)) {
+            message = MessageUtils.message(code, args);
+        }
+        if (message == null) {
+            message = defaultMessage;
+        }
+        return message;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java
new file mode 100644
index 0000000..8ee9e90
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileException.java
@@ -0,0 +1,21 @@
+package com.ruoyi.common.core.exception.file;
+
+import com.ruoyi.common.core.exception.base.BaseException;
+
+import java.io.Serial;
+
+/**
+ * 鏂囦欢淇℃伅寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class FileException extends BaseException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public FileException(String code, Object[] args) {
+        super("file", code, args, null);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..6d70b65
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.exception.file;
+
+import java.io.Serial;
+
+/**
+ * 鏂囦欢鍚嶇О瓒呴暱闄愬埗寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class FileNameLengthLimitExceededException extends FileException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public FileNameLengthLimitExceededException(int defaultFileNameLength) {
+        super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..940ae59
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.exception.file;
+
+import java.io.Serial;
+
+/**
+ * 鏂囦欢鍚嶅ぇ灏忛檺鍒跺紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class FileSizeLimitExceededException extends FileException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public FileSizeLimitExceededException(long defaultMaxSize) {
+        super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaException.java
new file mode 100644
index 0000000..700a501
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.exception.user;
+
+import java.io.Serial;
+
+/**
+ * 楠岃瘉鐮侀敊璇紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class CaptchaException extends UserException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaException() {
+        super("user.jcaptcha.error");
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java
new file mode 100644
index 0000000..9cffe64
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/CaptchaExpireException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.exception.user;
+
+import java.io.Serial;
+
+/**
+ * 楠岃瘉鐮佸け鏁堝紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class CaptchaExpireException extends UserException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public CaptchaExpireException() {
+        super("user.jcaptcha.expire");
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
new file mode 100644
index 0000000..4a9425c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserException.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.core.exception.user;
+
+import com.ruoyi.common.core.exception.base.BaseException;
+
+import java.io.Serial;
+
+/**
+ * 鐢ㄦ埛淇℃伅寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class UserException extends BaseException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public UserException(String code, Object... args) {
+        super("user", code, args, null);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..561b0cf
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.core.exception.user;
+
+import java.io.Serial;
+
+/**
+ * 鐢ㄦ埛瀵嗙爜涓嶆纭垨涓嶇鍚堣鑼冨紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class UserPasswordNotMatchException extends UserException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotMatchException() {
+        super("user.password.not.match");
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordRetryLimitExceedException.java
new file mode 100644
index 0000000..41719a1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/user/UserPasswordRetryLimitExceedException.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.core.exception.user;
+
+import java.io.Serial;
+
+/**
+ * 鐢ㄦ埛閿欒鏈�澶ф鏁板紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class UserPasswordRetryLimitExceedException extends UserException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) {
+        super("user.password.retry.limit.exceed", retryLimitCount, lockTime);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/BigNumberSerializer.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/BigNumberSerializer.java
new file mode 100644
index 0000000..0882c14
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/BigNumberSerializer.java
@@ -0,0 +1,42 @@
+package com.ruoyi.common.core.jackson;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
+import com.fasterxml.jackson.databind.ser.std.NumberSerializer;
+
+import java.io.IOException;
+
+/**
+ * 瓒呭嚭 JS 鏈�澶ф渶灏忓�� 澶勭悊
+ *
+ * @author Lion Li
+ */
+@JacksonStdImpl
+public class BigNumberSerializer extends NumberSerializer {
+
+    /**
+     * 鏍规嵁 JS Number.MAX_SAFE_INTEGER 涓� Number.MIN_SAFE_INTEGER 寰楁潵
+     */
+    private static final long MAX_SAFE_INTEGER = 9007199254740991L;
+    private static final long MIN_SAFE_INTEGER = -9007199254740991L;
+
+    /**
+     * 鎻愪緵瀹炰緥
+     */
+    public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);
+
+    public BigNumberSerializer(Class<? extends Number> rawType) {
+        super(rawType);
+    }
+
+    @Override
+    public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+        // 瓒呭嚭鑼冨洿 搴忓垪鍖栦綅瀛楃涓�
+        if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
+            super.serialize(value, gen, provider);
+        } else {
+            gen.writeString(value.toString());
+        }
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/SensitiveJsonSerializer.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/SensitiveJsonSerializer.java
new file mode 100644
index 0000000..946c5c3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/jackson/SensitiveJsonSerializer.java
@@ -0,0 +1,54 @@
+package com.ruoyi.common.core.jackson;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.ruoyi.common.core.annotation.Sensitive;
+import com.ruoyi.common.core.enums.SensitiveStrategy;
+import com.ruoyi.common.core.service.SensitiveService;
+import com.ruoyi.common.core.utils.SpringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * 鏁版嵁鑴辨晱json搴忓垪鍖栧伐鍏�
+ *
+ * @author Yjoioooo
+ */
+@Slf4j
+public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
+
+    private SensitiveStrategy strategy;
+
+    @Override
+    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+        try {
+            SensitiveService sensitiveService = SpringUtils.getBean(SensitiveService.class);
+            if (ObjectUtil.isNotNull(sensitiveService) && sensitiveService.isSensitive()) {
+                gen.writeString(strategy.desensitizer().apply(value));
+            } else {
+                gen.writeString(value);
+            }
+        } catch (BeansException e) {
+            log.error("鑴辨晱瀹炵幇涓嶅瓨鍦�, 閲囩敤榛樿澶勭悊 => {}", e.getMessage());
+            gen.writeString(value);
+        }
+    }
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
+        Sensitive annotation = property.getAnnotation(Sensitive.class);
+        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
+            this.strategy = annotation.strategy();
+            return this;
+        }
+        return prov.findValueSerializer(property.getType(), property);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/manager/ShutdownManager.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/manager/ShutdownManager.java
new file mode 100644
index 0000000..ba1629b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/manager/ShutdownManager.java
@@ -0,0 +1,41 @@
+package com.ruoyi.common.core.manager;
+
+import com.ruoyi.common.core.utils.Threads;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+import jakarta.annotation.PreDestroy;
+import java.util.concurrent.ScheduledExecutorService;
+
+/**
+ * 纭繚搴旂敤閫�鍑烘椂鑳藉叧闂悗鍙扮嚎绋�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@Component
+public class ShutdownManager {
+
+    @Autowired
+    @Qualifier("scheduledExecutorService")
+    private ScheduledExecutorService scheduledExecutorService;
+
+    @PreDestroy
+    public void destroy() {
+        shutdownAsyncManager();
+    }
+
+    /**
+     * 鍋滄寮傛鎵ц浠诲姟
+     */
+    private void shutdownAsyncManager() {
+        try {
+            log.info("====鍏抽棴鍚庡彴浠诲姟浠诲姟绾跨▼姹�====");
+            Threads.shutdownAndAwaitTermination(scheduledExecutorService);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/ConfigService.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/ConfigService.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/service/ConfigService.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/ConfigService.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/DictService.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DictService.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/service/DictService.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/DictService.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/SensitiveService.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/SensitiveService.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/service/SensitiveService.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/service/SensitiveService.java
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BeanCopyUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BeanCopyUtils.java
new file mode 100644
index 0000000..0661d9e
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BeanCopyUtils.java
@@ -0,0 +1,204 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.SimpleCache;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.springframework.cglib.beans.BeanCopier;
+import org.springframework.cglib.beans.BeanMap;
+import org.springframework.cglib.core.Converter;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * bean娣辨嫹璐濆伐鍏�(鍩轰簬 cglib 鎬ц兘浼樺紓)
+ * <p>
+ * 閲嶇偣 cglib 涓嶆敮鎸� 鎷疯礉鍒伴摼寮忓璞�
+ * 渚嬪: 婧愬璞� 鎷疯礉鍒� 鐩爣(閾惧紡瀵硅薄)
+ * 璇峰尯鍒嗗ソ`娴呮嫹璐漙鍜宍娣辨嫹璐漙鍐嶅仛浣跨敤
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class BeanCopyUtils {
+
+    /**
+     * 鍗曞璞″熀浜巆lass鍒涘缓鎷疯礉
+     *
+     * @param source 鏁版嵁鏉ユ簮瀹炰綋
+     * @param desc   鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
+     * @return desc
+     */
+    public static <T, V> V copy(T source, Class<V> desc) {
+        if (ObjectUtil.isNull(source)) {
+            return null;
+        }
+        if (ObjectUtil.isNull(desc)) {
+            return null;
+        }
+        final V target = ReflectUtil.newInstanceIfPossible(desc);
+        return copy(source, target);
+    }
+
+    /**
+     * 鍗曞璞″熀浜庡璞″垱寤烘嫹璐�
+     *
+     * @param source 鏁版嵁鏉ユ簮瀹炰綋
+     * @param desc   杞崲鍚庣殑瀵硅薄
+     * @return desc
+     */
+    public static <T, V> V copy(T source, V desc) {
+        if (ObjectUtil.isNull(source)) {
+            return null;
+        }
+        if (ObjectUtil.isNull(desc)) {
+            return null;
+        }
+        BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null);
+        beanCopier.copy(source, desc, null);
+        return desc;
+    }
+
+    /**
+     * 鍒楄〃瀵硅薄鍩轰簬class鍒涘缓鎷疯礉
+     *
+     * @param sourceList 鏁版嵁鏉ユ簮瀹炰綋鍒楄〃
+     * @param desc       鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
+     * @return desc
+     */
+    public static <T, V> List<V> copyList(List<T> sourceList, Class<V> desc) {
+        if (ObjectUtil.isNull(sourceList)) {
+            return null;
+        }
+        if (CollUtil.isEmpty(sourceList)) {
+            return CollUtil.newArrayList();
+        }
+        return StreamUtils.toList(sourceList, source -> {
+            V target = ReflectUtil.newInstanceIfPossible(desc);
+            copy(source, target);
+            return target;
+        });
+    }
+
+    /**
+     * bean鎷疯礉鍒癿ap
+     *
+     * @param bean 鏁版嵁鏉ユ簮瀹炰綋
+     * @return map瀵硅薄
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Map<String, Object> copyToMap(T bean) {
+        if (ObjectUtil.isNull(bean)) {
+            return null;
+        }
+        return BeanMap.create(bean);
+    }
+
+    /**
+     * map鎷疯礉鍒癰ean
+     *
+     * @param map       鏁版嵁鏉ユ簮
+     * @param beanClass bean绫�
+     * @return bean瀵硅薄
+     */
+    public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
+        if (MapUtil.isEmpty(map)) {
+            return null;
+        }
+        if (ObjectUtil.isNull(beanClass)) {
+            return null;
+        }
+        T bean = ReflectUtil.newInstanceIfPossible(beanClass);
+        return mapToBean(map, bean);
+    }
+
+    /**
+     * map鎷疯礉鍒癰ean
+     *
+     * @param map  鏁版嵁鏉ユ簮
+     * @param bean bean瀵硅薄
+     * @return bean瀵硅薄
+     */
+    public static <T> T mapToBean(Map<String, Object> map, T bean) {
+        if (MapUtil.isEmpty(map)) {
+            return null;
+        }
+        if (ObjectUtil.isNull(bean)) {
+            return null;
+        }
+        BeanMap.create(bean).putAll(map);
+        return bean;
+    }
+
+    /**
+     * map鎷疯礉鍒癿ap
+     *
+     * @param map   鏁版嵁鏉ユ簮
+     * @param clazz 杩斿洖鐨勫璞$被鍨�
+     * @return map瀵硅薄
+     */
+    public static <T, V> Map<String, V> mapToMap(Map<String, T> map, Class<V> clazz) {
+        if (MapUtil.isEmpty(map)) {
+            return null;
+        }
+        if (ObjectUtil.isNull(clazz)) {
+            return null;
+        }
+        Map<String, V> copyMap = new LinkedHashMap<>(map.size());
+        map.forEach((k, v) -> copyMap.put(k, copy(v, clazz)));
+        return copyMap;
+    }
+
+    /**
+     * BeanCopier灞炴�х紦瀛�<br>
+     * 缂撳瓨鐢ㄤ簬闃叉澶氭鍙嶅皠閫犳垚鐨勬�ц兘闂
+     *
+     * @author Looly
+     * @since 5.4.1
+     */
+    public enum BeanCopierCache {
+        /**
+         * BeanCopier灞炴�х紦瀛樺崟渚�
+         */
+        INSTANCE;
+
+        private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
+
+        /**
+         * 鑾峰緱绫讳笌杞崲鍣ㄧ敓鎴愮殑key鍦▄@link BeanCopier}鐨凪ap涓搴旂殑鍏冪礌
+         *
+         * @param srcClass    婧怋ean鐨勭被
+         * @param targetClass 鐩爣Bean鐨勭被
+         * @param converter   杞崲鍣�
+         * @return Map涓搴旂殑BeanCopier
+         */
+        public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Converter converter) {
+            final String key = genKey(srcClass, targetClass, converter);
+            return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null));
+        }
+
+        /**
+         * 鑾峰緱绫讳笌杞崲鍣ㄧ敓鎴愮殑key
+         *
+         * @param srcClass    婧怋ean鐨勭被
+         * @param targetClass 鐩爣Bean鐨勭被
+         * @param converter   杞崲鍣�
+         * @return 灞炴�у悕鍜孧ap鏄犲皠鐨刱ey
+         */
+        private String genKey(Class<?> srcClass, Class<?> targetClass, Converter converter) {
+            final StringBuilder key = StrUtil.builder()
+                .append(srcClass.getName()).append('#').append(targetClass.getName());
+            if (null != converter) {
+                key.append('#').append(converter.getClass().getName());
+            }
+            return key.toString();
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java
new file mode 100644
index 0000000..804f1a2
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java
@@ -0,0 +1,168 @@
+package com.ruoyi.common.core.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+/**
+ * 鏃堕棿宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
+
+    public static final String YYYY = "yyyy";
+
+    public static final String YYYY_MM = "yyyy-MM";
+
+    public static final String YYYY_MM_DD = "yyyy-MM-dd";
+
+    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    private static final String[] PARSE_PATTERNS = {
+        "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+        "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+        "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+    /**
+     * 鑾峰彇褰撳墠Date鍨嬫棩鏈�
+     *
+     * @return Date() 褰撳墠鏃ユ湡
+     */
+    public static Date getNowDate() {
+        return new Date();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃ユ湡, 榛樿鏍煎紡涓簓yyy-MM-dd
+     *
+     * @return String
+     */
+    public static String getDate() {
+        return dateTimeNow(YYYY_MM_DD);
+    }
+
+    public static String getTime() {
+        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+    }
+
+    public static String dateTimeNow() {
+        return dateTimeNow(YYYYMMDDHHMMSS);
+    }
+
+    public static String dateTimeNow(final String format) {
+        return parseDateToStr(format, new Date());
+    }
+
+    public static String dateTime(final Date date) {
+        return parseDateToStr(YYYY_MM_DD, date);
+    }
+
+    public static String parseDateToStr(final String format, final Date date) {
+        return new SimpleDateFormat(format).format(date);
+    }
+
+    public static Date dateTime(final String format, final String ts) {
+        try {
+            return new SimpleDateFormat(format).parse(ts);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�2018/08/08
+     */
+    public static String datePath() {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyy/MM/dd");
+    }
+
+    /**
+     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�20180808
+     */
+    public static String dateTime() {
+        Date now = new Date();
+        return DateFormatUtils.format(now, "yyyyMMdd");
+    }
+
+    /**
+     * 鏃ユ湡鍨嬪瓧绗︿覆杞寲涓烘棩鏈� 鏍煎紡
+     */
+    public static Date parseDate(Object str) {
+        if (str == null) {
+            return null;
+        }
+        try {
+            return parseDate(str.toString(), PARSE_PATTERNS);
+        } catch (ParseException e) {
+            return null;
+        }
+    }
+
+    /**
+     * 鑾峰彇鏈嶅姟鍣ㄥ惎鍔ㄦ椂闂�
+     */
+    public static Date getServerStartDate() {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        return new Date(time);
+    }
+
+    /**
+     * 璁$畻鐩稿樊澶╂暟
+     */
+    public static int differentDaysByMillisecond(Date date1, Date date2) {
+        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+    }
+
+    /**
+     * 璁$畻涓や釜鏃堕棿宸�
+     */
+    public static String getDatePoor(Date endDate, Date nowDate) {
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+        // long ns = 1000;
+        // 鑾峰緱涓や釜鏃堕棿鐨勬绉掓椂闂村樊寮�
+        long diff = endDate.getTime() - nowDate.getTime();
+        // 璁$畻宸灏戝ぉ
+        long day = diff / nd;
+        // 璁$畻宸灏戝皬鏃�
+        long hour = diff % nd / nh;
+        // 璁$畻宸灏戝垎閽�
+        long min = diff % nd % nh / nm;
+        // 璁$畻宸灏戠//杈撳嚭缁撴灉
+        // long sec = diff % nd % nh % nm / ns;
+        return day + "澶�" + hour + "灏忔椂" + min + "鍒嗛挓";
+    }
+
+    /**
+     * 澧炲姞 LocalDateTime ==> Date
+     */
+    public static Date toDate(LocalDateTime temporalAccessor) {
+        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+
+    /**
+     * 澧炲姞 LocalDate ==> Date
+     */
+    public static Date toDate(LocalDate temporalAccessor) {
+        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+        return Date.from(zdt.toInstant());
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JsonUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JsonUtils.java
new file mode 100644
index 0000000..f8245b3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/JsonUtils.java
@@ -0,0 +1,111 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * JSON 宸ュ叿绫�
+ *
+ * @author 鑺嬮亾婧愮爜
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class JsonUtils {
+
+    private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class);
+
+    public static ObjectMapper getObjectMapper() {
+        return OBJECT_MAPPER;
+    }
+
+    public static String toJsonString(Object object) {
+        if (ObjectUtil.isNull(object)) {
+            return null;
+        }
+        try {
+            return OBJECT_MAPPER.writeValueAsString(object);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> T parseObject(String text, Class<T> clazz) {
+        if (StringUtils.isEmpty(text)) {
+            return null;
+        }
+        try {
+            return OBJECT_MAPPER.readValue(text, clazz);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
+        if (ArrayUtil.isEmpty(bytes)) {
+            return null;
+        }
+        try {
+            return OBJECT_MAPPER.readValue(bytes, clazz);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> T parseObject(String text, TypeReference<T> typeReference) {
+        if (StringUtils.isBlank(text)) {
+            return null;
+        }
+        try {
+            return OBJECT_MAPPER.readValue(text, typeReference);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Dict parseMap(String text) {
+        if (StringUtils.isBlank(text)) {
+            return null;
+        }
+        try {
+            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class));
+        } catch (MismatchedInputException e) {
+            // 绫诲瀷涓嶅尮閰嶈鏄庝笉鏄痡son
+            return null;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static List<Dict> parseArrayMap(String text) {
+        if (StringUtils.isBlank(text)) {
+            return null;
+        }
+        try {
+            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Dict.class));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static <T> List<T> parseArray(String text, Class<T> clazz) {
+        if (StringUtils.isEmpty(text)) {
+            return new ArrayList<>();
+        }
+        try {
+            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java
new file mode 100644
index 0000000..24928f8
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/MessageUtils.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.core.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+
+/**
+ * 鑾峰彇i18n璧勬簮鏂囦欢
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class MessageUtils {
+
+    private static final MessageSource MESSAGE_SOURCE = SpringUtils.getBean(MessageSource.class);
+
+    /**
+     * 鏍规嵁娑堟伅閿拰鍙傛暟 鑾峰彇娑堟伅 濮旀墭缁檚pring messageSource
+     *
+     * @param code 娑堟伅閿�
+     * @param args 鍙傛暟
+     * @return 鑾峰彇鍥介檯鍖栫炕璇戝��
+     */
+    public static String message(String code, Object... args) {
+        return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java
new file mode 100644
index 0000000..46475c7
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java
@@ -0,0 +1,203 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.extra.servlet.JakartaServletUtil;
+import cn.hutool.http.HttpStatus;
+import com.ruoyi.common.core.constant.Constants;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpSession;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+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 java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 瀹㈡埛绔伐鍏风被
+ *
+ * @author ruoyi
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ServletUtils extends JakartaServletUtil {
+
+    /**
+     * 鑾峰彇String鍙傛暟
+     */
+    public static String getParameter(String name) {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 鑾峰彇String鍙傛暟
+     */
+    public static String getParameter(String name, String defaultValue) {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰彇Integer鍙傛暟
+     */
+    public static Integer getParameterToInt(String name) {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 鑾峰彇Integer鍙傛暟
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue) {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰彇Boolean鍙傛暟
+     */
+    public static Boolean getParameterToBool(String name) {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 鑾峰彇Boolean鍙傛暟
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue) {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+     *
+     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String[]> getParams(ServletRequest request) {
+        final Map<String, String[]> map = request.getParameterMap();
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+     *
+     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String> getParamMap(ServletRequest request) {
+        Map<String, String> params = new HashMap<>();
+        for (Map.Entry<String, String[]> entry : getParams(request).entrySet()) {
+            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+        }
+        return params;
+    }
+
+    /**
+     * 鑾峰彇request
+     */
+    public static HttpServletRequest getRequest() {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 鑾峰彇response
+     */
+    public static HttpServletResponse getResponse() {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 鑾峰彇session
+     */
+    public static HttpSession getSession() {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes() {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 灏嗗瓧绗︿覆娓叉煋鍒板鎴风
+     *
+     * @param response 娓叉煋瀵硅薄
+     * @param string   寰呮覆鏌撶殑瀛楃涓�
+     */
+    public static void renderString(HttpServletResponse response, String string) {
+        try {
+            response.setStatus(HttpStatus.HTTP_OK);
+            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
+            response.getWriter().print(string);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 鏄惁鏄疉jax寮傛璇锋眰
+     *
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request) {
+
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml");
+    }
+
+    public static String getClientIP() {
+        return getClientIP(getRequest());
+    }
+
+    /**
+     * 鍐呭缂栫爜
+     *
+     * @param str 鍐呭
+     * @return 缂栫爜鍚庣殑鍐呭
+     */
+    public static String urlEncode(String str) {
+        try {
+            return URLEncoder.encode(str, Constants.UTF8);
+        } catch (UnsupportedEncodingException e) {
+            return StringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 鍐呭瑙g爜
+     *
+     * @param str 鍐呭
+     * @return 瑙g爜鍚庣殑鍐呭
+     */
+    public static String urlDecode(String str) {
+        try {
+            return URLDecoder.decode(str, Constants.UTF8);
+        } catch (UnsupportedEncodingException e) {
+            return StringUtils.EMPTY;
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java
new file mode 100644
index 0000000..807700d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SpringUtils.java
@@ -0,0 +1,74 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.extra.spring.SpringUtil;
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring宸ュ叿绫�
+ *
+ * @author Lion Li
+ */
+@Component
+public final class SpringUtils extends SpringUtil {
+
+    /**
+     * 濡傛灉BeanFactory鍖呭惈涓�涓笌鎵�缁欏悕绉板尮閰嶇殑bean瀹氫箟锛屽垯杩斿洖true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name) {
+        return getBeanFactory().containsBean(name);
+    }
+
+    /**
+     * 鍒ゆ柇浠ョ粰瀹氬悕瀛楁敞鍐岀殑bean瀹氫箟鏄竴涓猻ingleton杩樻槸涓�涓猵rototype銆�
+     * 濡傛灉涓庣粰瀹氬悕瀛楃浉搴旂殑bean瀹氫箟娌℃湁琚壘鍒帮紝灏嗕細鎶涘嚭涓�涓紓甯革紙NoSuchBeanDefinitionException锛�
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
+        return getBeanFactory().isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 娉ㄥ唽瀵硅薄鐨勭被鍨�
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
+        return getBeanFactory().getType(name);
+    }
+
+    /**
+     * 濡傛灉缁欏畾鐨刡ean鍚嶅瓧鍦╞ean瀹氫箟涓湁鍒悕锛屽垯杩斿洖杩欎簺鍒悕
+     *
+     * @param name
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
+        return getBeanFactory().getAliases(name);
+    }
+
+    /**
+     * 鑾峰彇aop浠g悊瀵硅薄
+     *
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker) {
+        return (T) AopContext.currentProxy();
+    }
+
+
+    /**
+     * 鑾峰彇spring涓婁笅鏂�
+     */
+    public static ApplicationContext context() {
+        return getApplicationContext();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StreamUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StreamUtils.java
new file mode 100644
index 0000000..b11fa51
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StreamUtils.java
@@ -0,0 +1,251 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * stream 娴佸伐鍏风被
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class StreamUtils {
+
+    /**
+     * 灏哻ollection杩囨护
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param function   杩囨护鏂规硶
+     * @return 杩囨护鍚庣殑list
+     */
+    public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) {
+        if (CollUtil.isEmpty(collection)) {
+            return CollUtil.newArrayList();
+        }
+        return collection.stream().filter(function).collect(Collectors.toList());
+    }
+
+    /**
+     * 灏哻ollection鎷兼帴
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param function   鎷兼帴鏂规硶
+     * @return 鎷兼帴鍚庣殑list
+     */
+    public static <E> String join(Collection<E> collection, Function<E, String> function) {
+        return join(collection, function, ",");
+    }
+
+    /**
+     * 灏哻ollection鎷兼帴
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param function   鎷兼帴鏂规硶
+     * @param delimiter  鎷兼帴绗�
+     * @return 鎷兼帴鍚庣殑list
+     */
+    public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
+        if (CollUtil.isEmpty(collection)) {
+            return StringUtils.EMPTY;
+        }
+        return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
+    }
+
+    /**
+     * 灏哻ollection鎺掑簭
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param comparing  鎺掑簭鏂规硶
+     * @return 鎺掑簭鍚庣殑list
+     */
+    public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) {
+        if (CollUtil.isEmpty(collection)) {
+            return CollUtil.newArrayList();
+        }
+        return collection.stream().sorted(comparing).collect(Collectors.toList());
+    }
+
+    /**
+     * 灏哻ollection杞寲涓虹被鍨嬩笉鍙樼殑map<br>
+     * <B>{@code Collection<V>  ---->  Map<K,V>}</B>
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param key        V绫诲瀷杞寲涓篕绫诲瀷鐨刲ambda鏂规硶
+     * @param <V>        collection涓殑娉涘瀷
+     * @param <K>        map涓殑key绫诲瀷
+     * @return 杞寲鍚庣殑map
+     */
+    public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
+        if (CollUtil.isEmpty(collection)) {
+            return MapUtil.newHashMap();
+        }
+        return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
+    }
+
+    /**
+     * 灏咰ollection杞寲涓簃ap(value绫诲瀷涓巆ollection鐨勬硾鍨嬩笉鍚�)<br>
+     * <B>{@code Collection<E> -----> Map<K,V>  }</B>
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param key        E绫诲瀷杞寲涓篕绫诲瀷鐨刲ambda鏂规硶
+     * @param value      E绫诲瀷杞寲涓篤绫诲瀷鐨刲ambda鏂规硶
+     * @param <E>        collection涓殑娉涘瀷
+     * @param <K>        map涓殑key绫诲瀷
+     * @param <V>        map涓殑value绫诲瀷
+     * @return 杞寲鍚庣殑map
+     */
+    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
+        if (CollUtil.isEmpty(collection)) {
+            return MapUtil.newHashMap();
+        }
+        return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
+    }
+
+    /**
+     * 灏哻ollection鎸夌収瑙勫垯(姣斿鏈夌浉鍚岀殑鐝骇id)鍒嗙被鎴恗ap<br>
+     * <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
+     *
+     * @param collection 闇�瑕佸垎绫荤殑闆嗗悎
+     * @param key        鍒嗙被鐨勮鍒�
+     * @param <E>        collection涓殑娉涘瀷
+     * @param <K>        map涓殑key绫诲瀷
+     * @return 鍒嗙被鍚庣殑map
+     */
+    public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
+        if (CollUtil.isEmpty(collection)) {
+            return MapUtil.newHashMap();
+        }
+        return collection
+            .stream()
+            .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
+    }
+
+    /**
+     * 灏哻ollection鎸夌収涓や釜瑙勫垯(姣斿鏈夌浉鍚岀殑骞寸骇id,鐝骇id)鍒嗙被鎴愬弻灞俶ap<br>
+     * <B>{@code Collection<E>  --->  Map<T,Map<U,List<E>>> } </B>
+     *
+     * @param collection 闇�瑕佸垎绫荤殑闆嗗悎
+     * @param key1       绗竴涓垎绫荤殑瑙勫垯
+     * @param key2       绗簩涓垎绫荤殑瑙勫垯
+     * @param <E>        闆嗗悎鍏冪礌绫诲瀷
+     * @param <K>        绗竴涓猰ap涓殑key绫诲瀷
+     * @param <U>        绗簩涓猰ap涓殑key绫诲瀷
+     * @return 鍒嗙被鍚庣殑map
+     */
+    public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) {
+        if (CollUtil.isEmpty(collection)) {
+            return MapUtil.newHashMap();
+        }
+        return collection
+            .stream()
+            .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
+    }
+
+    /**
+     * 灏哻ollection鎸夌収涓や釜瑙勫垯(姣斿鏈夌浉鍚岀殑骞寸骇id,鐝骇id)鍒嗙被鎴愬弻灞俶ap<br>
+     * <B>{@code Collection<E>  --->  Map<T,Map<U,E>> } </B>
+     *
+     * @param collection 闇�瑕佸垎绫荤殑闆嗗悎
+     * @param key1       绗竴涓垎绫荤殑瑙勫垯
+     * @param key2       绗簩涓垎绫荤殑瑙勫垯
+     * @param <T>        绗竴涓猰ap涓殑key绫诲瀷
+     * @param <U>        绗簩涓猰ap涓殑key绫诲瀷
+     * @param <E>        collection涓殑娉涘瀷
+     * @return 鍒嗙被鍚庣殑map
+     */
+    public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) {
+        if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
+            return MapUtil.newHashMap();
+        }
+        return collection
+            .stream()
+            .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
+    }
+
+    /**
+     * 灏哻ollection杞寲涓篖ist闆嗗悎锛屼絾鏄袱鑰呯殑娉涘瀷涓嶅悓<br>
+     * <B>{@code Collection<E>  ------>  List<T> } </B>
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param function   collection涓殑娉涘瀷杞寲涓簂ist娉涘瀷鐨刲ambda琛ㄨ揪寮�
+     * @param <E>        collection涓殑娉涘瀷
+     * @param <T>        List涓殑娉涘瀷
+     * @return 杞寲鍚庣殑list
+     */
+    public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
+        if (CollUtil.isEmpty(collection)) {
+            return CollUtil.newArrayList();
+        }
+        return collection
+            .stream()
+            .map(function)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toList());
+    }
+
+    /**
+     * 灏哻ollection杞寲涓篠et闆嗗悎锛屼絾鏄袱鑰呯殑娉涘瀷涓嶅悓<br>
+     * <B>{@code Collection<E>  ------>  Set<T> } </B>
+     *
+     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
+     * @param function   collection涓殑娉涘瀷杞寲涓簊et娉涘瀷鐨刲ambda琛ㄨ揪寮�
+     * @param <E>        collection涓殑娉涘瀷
+     * @param <T>        Set涓殑娉涘瀷
+     * @return 杞寲鍚庣殑Set
+     */
+    public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
+        if (CollUtil.isEmpty(collection) || function == null) {
+            return CollUtil.newHashSet();
+        }
+        return collection
+            .stream()
+            .map(function)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+    }
+
+
+    /**
+     * 鍚堝苟涓や釜鐩稿悓key绫诲瀷鐨刴ap
+     *
+     * @param map1  绗竴涓渶瑕佸悎骞剁殑 map
+     * @param map2  绗簩涓渶瑕佸悎骞剁殑 map
+     * @param merge 鍚堝苟鐨刲ambda锛屽皢key  value1 value2鍚堝苟鎴愭渶缁堢殑绫诲瀷,娉ㄦ剰value鍙兘涓虹┖鐨勬儏鍐�
+     * @param <K>   map涓殑key绫诲瀷
+     * @param <X>   绗竴涓� map鐨剉alue绫诲瀷
+     * @param <Y>   绗簩涓� map鐨剉alue绫诲瀷
+     * @param <V>   鏈�缁坢ap鐨剉alue绫诲瀷
+     * @return 鍚堝苟鍚庣殑map
+     */
+    public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) {
+        if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) {
+            return MapUtil.newHashMap();
+        } else if (MapUtil.isEmpty(map1)) {
+            map1 = MapUtil.newHashMap();
+        } else if (MapUtil.isEmpty(map2)) {
+            map2 = MapUtil.newHashMap();
+        }
+        Set<K> key = new HashSet<>();
+        key.addAll(map1.keySet());
+        key.addAll(map2.keySet());
+        Map<K, V> map = new HashMap<>();
+        for (K t : key) {
+            X x = map1.get(t);
+            Y y = map2.get(t);
+            V z = merge.apply(x, y);
+            if (z != null) {
+                map.put(t, z);
+            }
+        }
+        return map;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java
new file mode 100644
index 0000000..15ece20
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java
@@ -0,0 +1,273 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.StrUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.springframework.util.AntPathMatcher;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 瀛楃涓插伐鍏风被
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+    /**
+     * 鑾峰彇鍙傛暟涓嶄负绌哄��
+     *
+     * @param str defaultValue 瑕佸垽鏂殑value
+     * @return value 杩斿洖鍊�
+     */
+    public static String blankToDefault(String str, String defaultValue) {
+        return StrUtil.blankToDefault(str, defaultValue);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓虹┖涓�
+     *
+     * @param str String
+     * @return true锛氫负绌� false锛氶潪绌�
+     */
+    public static boolean isEmpty(String str) {
+        return StrUtil.isEmpty(str);
+    }
+
+    /**
+     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓洪潪绌轰覆
+     *
+     * @param str String
+     * @return true锛氶潪绌轰覆 false锛氱┖涓�
+     */
+    public static boolean isNotEmpty(String str) {
+        return !isEmpty(str);
+    }
+
+    /**
+     * 鍘荤┖鏍�
+     */
+    public static String trim(String str) {
+        return StrUtil.trim(str);
+    }
+
+    /**
+     * 鎴彇瀛楃涓�
+     *
+     * @param str   瀛楃涓�
+     * @param start 寮�濮�
+     * @return 缁撴灉
+     */
+    public static String substring(final String str, int start) {
+        return substring(str, start, str.length());
+    }
+
+    /**
+     * 鎴彇瀛楃涓�
+     *
+     * @param str   瀛楃涓�
+     * @param start 寮�濮�
+     * @param end   缁撴潫
+     * @return 缁撴灉
+     */
+    public static String substring(final String str, int start, int end) {
+        return StrUtil.sub(str, start, end);
+    }
+
+    /**
+     * 鏍煎紡鍖栨枃鏈�, {} 琛ㄧず鍗犱綅绗�<br>
+     * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+     * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+     * 渚嬶細<br>
+     * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is {} for a<br>
+     * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     *
+     * @param template 鏂囨湰妯℃澘锛岃鏇挎崲鐨勯儴鍒嗙敤 {} 琛ㄧず
+     * @param params   鍙傛暟鍊�
+     * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
+     */
+    public static String format(String template, Object... params) {
+        return StrUtil.format(template, params);
+    }
+
+    /**
+     * 鏄惁涓篽ttp(s)://寮�澶�
+     *
+     * @param link 閾炬帴
+     * @return 缁撴灉
+     */
+    public static boolean ishttp(String link) {
+        return Validator.isUrl(link);
+    }
+
+    /**
+     * 瀛楃涓茶浆set
+     *
+     * @param str 瀛楃涓�
+     * @param sep 鍒嗛殧绗�
+     * @return set闆嗗悎
+     */
+    public static Set<String> str2Set(String str, String sep) {
+        return new HashSet<>(str2List(str, sep, true, false));
+    }
+
+    /**
+     * 瀛楃涓茶浆list
+     *
+     * @param str         瀛楃涓�
+     * @param sep         鍒嗛殧绗�
+     * @param filterBlank 杩囨护绾┖鐧�
+     * @param trim        鍘绘帀棣栧熬绌虹櫧
+     * @return list闆嗗悎
+     */
+    public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
+        List<String> list = new ArrayList<>();
+        if (isEmpty(str)) {
+            return list;
+        }
+
+        // 杩囨护绌虹櫧瀛楃涓�
+        if (filterBlank && isBlank(str)) {
+            return list;
+        }
+        String[] split = str.split(sep);
+        for (String string : split) {
+            if (filterBlank && isBlank(string)) {
+                continue;
+            }
+            if (trim) {
+                string = trim(string);
+            }
+            list.add(string);
+        }
+
+        return list;
+    }
+
+    /**
+     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆鍚屾椂涓插拷鐣ュぇ灏忓啓
+     *
+     * @param cs                  鎸囧畾瀛楃涓�
+     * @param searchCharSequences 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+     * @return 鏄惁鍖呭惈浠绘剰涓�涓瓧绗︿覆
+     */
+    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
+        return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences);
+    }
+
+    /**
+     * 椹煎嘲杞笅鍒掔嚎鍛藉悕
+     */
+    public static String toUnderScoreCase(String str) {
+        return StrUtil.toUnderlineCase(str);
+    }
+
+    /**
+     * 鏄惁鍖呭惈瀛楃涓�
+     *
+     * @param str  楠岃瘉瀛楃涓�
+     * @param strs 瀛楃涓茬粍
+     * @return 鍖呭惈杩斿洖true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs) {
+        return StrUtil.equalsAnyIgnoreCase(str, strs);
+    }
+
+    /**
+     * 灏嗕笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆杞崲涓洪┘宄板紡銆傚鏋滆浆鎹㈠墠鐨勪笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆涓虹┖锛屽垯杩斿洖绌哄瓧绗︿覆銆� 渚嬪锛欻ELLO_WORLD->HelloWorld
+     *
+     * @param name 杞崲鍓嶇殑涓嬪垝绾垮ぇ鍐欐柟寮忓懡鍚嶇殑瀛楃涓�
+     * @return 杞崲鍚庣殑椹煎嘲寮忓懡鍚嶇殑瀛楃涓�
+     */
+    public static String convertToCamelCase(String name) {
+        return StrUtil.upperFirst(StrUtil.toCamelCase(name));
+    }
+
+    /**
+     * 椹煎嘲寮忓懡鍚嶆硶 渚嬪锛歶ser_name->userName
+     */
+    public static String toCamelCase(String s) {
+        return StrUtil.toCamelCase(s);
+    }
+
+    /**
+     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀尮閰嶆寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆
+     *
+     * @param str  鎸囧畾瀛楃涓�
+     * @param strs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+     * @return 鏄惁鍖归厤
+     */
+    public static boolean matches(String str, List<String> strs) {
+        if (isEmpty(str) || CollUtil.isEmpty(strs)) {
+            return false;
+        }
+        for (String pattern : strs) {
+            if (isMatch(pattern, str)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇url鏄惁涓庤鍒欓厤缃�:
+     * ? 琛ㄧず鍗曚釜瀛楃;
+     * * 琛ㄧず涓�灞傝矾寰勫唴鐨勪换鎰忓瓧绗︿覆锛屼笉鍙法灞傜骇;
+     * ** 琛ㄧず浠绘剰灞傝矾寰�;
+     *
+     * @param pattern 鍖归厤瑙勫垯
+     * @param url     闇�瑕佸尮閰嶇殑url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url) {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    /**
+     * 鏁板瓧宸﹁竟琛ラ綈0锛屼娇涔嬭揪鍒版寚瀹氶暱搴︺�傛敞鎰忥紝濡傛灉鏁板瓧杞崲涓哄瓧绗︿覆鍚庯紝闀垮害澶т簬size锛屽垯鍙繚鐣� 鏈�鍚巗ize涓瓧绗︺��
+     *
+     * @param num 鏁板瓧瀵硅薄
+     * @param size 瀛楃涓叉寚瀹氶暱搴�
+     * @return 杩斿洖鏁板瓧鐨勫瓧绗︿覆鏍煎紡锛岃瀛楃涓蹭负鎸囧畾闀垮害銆�
+     */
+    public static final String padl(final Number num, final int size) {
+        return padl(num.toString(), size, '0');
+    }
+
+    /**
+     * 瀛楃涓插乏琛ラ綈銆傚鏋滃師濮嬪瓧绗︿覆s闀垮害澶т簬size锛屽垯鍙繚鐣欐渶鍚巗ize涓瓧绗︺��
+     *
+     * @param s 鍘熷瀛楃涓�
+     * @param size 瀛楃涓叉寚瀹氶暱搴�
+     * @param c 鐢ㄤ簬琛ラ綈鐨勫瓧绗�
+     * @return 杩斿洖鎸囧畾闀垮害鐨勫瓧绗︿覆锛岀敱鍘熷瓧绗︿覆宸﹁ˉ榻愭垨鎴彇寰楀埌銆�
+     */
+    public static final String padl(final String s, final int size, final char c) {
+        final StringBuilder sb = new StringBuilder(size);
+        if (s != null) {
+            final int len = s.length();
+            if (s.length() <= size) {
+                for (int i = size - len; i > 0; i--) {
+                    sb.append(c);
+                }
+                sb.append(s);
+            } else {
+                return s.substring(len - size, len);
+            }
+        } else {
+            for (int i = size; i > 0; i--) {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/Threads.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/Threads.java
new file mode 100644
index 0000000..89ca662
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/Threads.java
@@ -0,0 +1,75 @@
+package com.ruoyi.common.core.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.*;
+
+/**
+ * 绾跨▼鐩稿叧宸ュ叿绫�.
+ *
+ * @author ruoyi
+ */
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class Threads {
+
+    /**
+     * sleep绛夊緟,鍗曚綅涓烘绉�
+     */
+    public static void sleep(long milliseconds) {
+        try {
+            Thread.sleep(milliseconds);
+        } catch (InterruptedException e) {
+            return;
+        }
+    }
+
+    /**
+     * 鍋滄绾跨▼姹�
+     * 鍏堜娇鐢╯hutdown, 鍋滄鎺ユ敹鏂颁换鍔″苟灏濊瘯瀹屾垚鎵�鏈夊凡瀛樺湪浠诲姟.
+     * 濡傛灉瓒呮椂, 鍒欒皟鐢╯hutdownNow, 鍙栨秷鍦╳orkQueue涓璓ending鐨勪换鍔�,骞朵腑鏂墍鏈夐樆濉炲嚱鏁�.
+     * 濡傛灉浠嶇劧瓒呮檪锛屽墖寮峰埗閫�鍑�.
+     * 鍙﹀鍦╯hutdown鏃剁嚎绋嬫湰韬璋冪敤涓柇鍋氫簡澶勭悊.
+     */
+    public static void shutdownAndAwaitTermination(ExecutorService pool) {
+        if (pool != null && !pool.isShutdown()) {
+            pool.shutdown();
+            try {
+                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
+                    pool.shutdownNow();
+                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
+                        log.info("Pool did not terminate");
+                    }
+                }
+            } catch (InterruptedException ie) {
+                pool.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    /**
+     * 鎵撳嵃绾跨▼寮傚父淇℃伅
+     */
+    public static void printException(Runnable r, Throwable t) {
+        if (t == null && r instanceof Future<?>) {
+            try {
+                Future<?> future = (Future<?>) r;
+                if (future.isDone()) {
+                    future.get();
+                }
+            } catch (CancellationException ce) {
+                t = ce;
+            } catch (ExecutionException ee) {
+                t = ee.getCause();
+            } catch (InterruptedException ie) {
+                Thread.currentThread().interrupt();
+            }
+        }
+        if (t != null) {
+            log.error(t.getMessage(), t);
+        }
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/TreeBuildUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/TreeBuildUtils.java
new file mode 100644
index 0000000..0d24945
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/TreeBuildUtils.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.core.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.lang.tree.TreeNodeConfig;
+import cn.hutool.core.lang.tree.TreeUtil;
+import cn.hutool.core.lang.tree.parser.NodeParser;
+import com.ruoyi.common.core.utils.reflect.ReflectUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 鎵╁睍 hutool TreeUtil 灏佽绯荤粺鏍戞瀯寤�
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class TreeBuildUtils extends TreeUtil {
+
+    /**
+     * 鏍规嵁鍓嶇瀹氬埗宸紓鍖栧瓧娈�
+     */
+    public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
+
+    public static <T, K> List<Tree<K>> build(List<T> list, NodeParser<T, K> nodeParser) {
+        if (CollUtil.isEmpty(list)) {
+            return null;
+        }
+        K k = ReflectUtils.invokeGetter(list.get(0), "parentId");
+        return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ValidatorUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ValidatorUtils.java
new file mode 100644
index 0000000..7b331f0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ValidatorUtils.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.core.utils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import jakarta.validation.Validator;
+import java.util.Set;
+
+/**
+ * Validator 鏍¢獙妗嗘灦宸ュ叿
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ValidatorUtils {
+
+    private static final Validator VALID = SpringUtils.getBean(Validator.class);
+
+    public static <T> void validate(T object, Class<?>... groups) {
+        Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
+        if (!validate.isEmpty()) {
+            throw new ConstraintViolationException("鍙傛暟鏍¢獙寮傚父", validate);
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java
new file mode 100644
index 0000000..119c77d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.core.utils.file;
+
+import cn.hutool.core.io.FileUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 鏂囦欢澶勭悊宸ュ叿绫�
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class FileUtils extends FileUtil {
+
+    /**
+     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+     *
+     * @param response     鍝嶅簲瀵硅薄
+     * @param realFileName 鐪熷疄鏂囦欢鍚�
+     */
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
+        String percentEncodedFileName = percentEncode(realFileName);
+
+        StringBuilder contentDispositionValue = new StringBuilder();
+        contentDispositionValue.append("attachment; filename=")
+            .append(percentEncodedFileName)
+            .append(";")
+            .append("filename*=")
+            .append("utf-8''")
+            .append(percentEncodedFileName);
+
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
+        response.setHeader("Content-disposition", contentDispositionValue.toString());
+        response.setHeader("download-filename", percentEncodedFileName);
+    }
+
+    /**
+     * 鐧惧垎鍙风紪鐮佸伐鍏锋柟娉�
+     *
+     * @param s 闇�瑕佺櫨鍒嗗彿缂栫爜鐨勫瓧绗︿覆
+     * @return 鐧惧垎鍙风紪鐮佸悗鐨勫瓧绗︿覆
+     */
+    public static String percentEncode(String s) throws UnsupportedEncodingException {
+        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+        return encode.replaceAll("\\+", "%20");
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/MimeTypeUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/MimeTypeUtils.java
new file mode 100644
index 0000000..7291c0f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/MimeTypeUtils.java
@@ -0,0 +1,40 @@
+package com.ruoyi.common.core.utils.file;
+
+/**
+ * 濯掍綋绫诲瀷宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class MimeTypeUtils {
+    public static final String IMAGE_PNG = "image/png";
+
+    public static final String IMAGE_JPG = "image/jpg";
+
+    public static final String IMAGE_JPEG = "image/jpeg";
+
+    public static final String IMAGE_BMP = "image/bmp";
+
+    public static final String IMAGE_GIF = "image/gif";
+
+    public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
+
+    public static final String[] FLASH_EXTENSION = {"swf", "flv"};
+
+    public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+        "asf", "rm", "rmvb"};
+
+    public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
+
+    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+        // 鍥剧墖
+        "bmp", "gif", "jpg", "jpeg", "png",
+        // word excel powerpoint
+        "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+        // 鍘嬬缉鏂囦欢
+        "rar", "zip", "gz", "bz2",
+        // 瑙嗛鏍煎紡
+        "mp4", "avi", "rmvb",
+        // pdf
+        "pdf"};
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java
new file mode 100644
index 0000000..15c3085
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ip/AddressUtils.java
@@ -0,0 +1,60 @@
+package com.ruoyi.common.core.utils.ip;
+
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.net.NetUtil;
+import cn.hutool.http.HtmlUtil;
+import cn.hutool.http.HttpUtil;
+import com.ruoyi.common.core.config.RuoYiConfig;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 鑾峰彇鍦板潃绫�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class AddressUtils {
+
+    // IP鍦板潃鏌ヨ
+    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
+
+    // 鏈煡鍦板潃
+    public static final String UNKNOWN = "XX XX";
+
+    public static String getRealAddressByIP(String ip) {
+        String address = UNKNOWN;
+        if (StringUtils.isBlank(ip)) {
+            return address;
+        }
+        // 鍐呯綉涓嶆煡璇�
+        ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
+        if (NetUtil.isInnerIP(ip)) {
+            return "鍐呯綉IP";
+        }
+        if (RuoYiConfig.isAddressEnabled()) {
+            try {
+                String rspStr = HttpUtil.createGet(IP_URL)
+                    .body("ip=" + ip + "&json=true", Constants.GBK)
+                    .execute()
+                    .body();
+                if (StringUtils.isEmpty(rspStr)) {
+                    log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
+                    return UNKNOWN;
+                }
+                Dict obj = JsonUtils.parseMap(rspStr);
+                String region = obj.getStr("pro");
+                String city = obj.getStr("city");
+                return String.format("%s %s", region, city);
+            } catch (Exception e) {
+                log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
+            }
+        }
+        return UNKNOWN;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/reflect/ReflectUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/reflect/ReflectUtils.java
new file mode 100644
index 0000000..af0c560
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/reflect/ReflectUtils.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.core.utils.reflect;
+
+import cn.hutool.core.util.ReflectUtil;
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.lang.reflect.Method;
+
+/**
+ * 鍙嶅皠宸ュ叿绫�. 鎻愪緵璋冪敤getter/setter鏂规硶, 璁块棶绉佹湁鍙橀噺, 璋冪敤绉佹湁鏂规硶, 鑾峰彇娉涘瀷绫诲瀷Class, 琚獳OP杩囩殑鐪熷疄绫荤瓑宸ュ叿鍑芥暟.
+ *
+ * @author Lion Li
+ */
+@SuppressWarnings("rawtypes")
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ReflectUtils extends ReflectUtil {
+
+    private static final String SETTER_PREFIX = "set";
+
+    private static final String GETTER_PREFIX = "get";
+
+    /**
+     * 璋冪敤Getter鏂规硶.
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> E invokeGetter(Object obj, String propertyName) {
+        Object object = obj;
+        for (String name : StringUtils.split(propertyName, ".")) {
+            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+            object = invoke(object, getterMethodName);
+        }
+        return (E) object;
+    }
+
+    /**
+     * 璋冪敤Setter鏂规硶, 浠呭尮閰嶆柟娉曞悕銆�
+     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+     */
+    public static <E> void invokeSetter(Object obj, String propertyName, E value) {
+        Object object = obj;
+        String[] names = StringUtils.split(propertyName, ".");
+        for (int i = 0; i < names.length; i++) {
+            if (i < names.length - 1) {
+                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+                object = invoke(object, getterMethodName);
+            } else {
+                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+                Method method = getMethodByName(object.getClass(), setterMethodName);
+                invoke(object, method, value);
+            }
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/sql/SqlUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/sql/SqlUtil.java
new file mode 100644
index 0000000..4c878d3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/sql/SqlUtil.java
@@ -0,0 +1,57 @@
+package com.ruoyi.common.core.utils.sql;
+
+import com.ruoyi.common.core.exception.UtilException;
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * sql鎿嶄綔宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class SqlUtil {
+
+    /**
+     * 瀹氫箟甯哥敤鐨� sql鍏抽敭瀛�
+     */
+    public static final String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
+
+    /**
+     * 浠呮敮鎸佸瓧姣嶃�佹暟瀛椼�佷笅鍒掔嚎銆佺┖鏍笺�侀�楀彿銆佸皬鏁扮偣锛堟敮鎸佸涓瓧娈垫帓搴忥級
+     */
+    public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+    /**
+     * 妫�鏌ュ瓧绗︼紝闃叉娉ㄥ叆缁曡繃
+     */
+    public static String escapeOrderBySql(String value) {
+        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
+            throw new UtilException("鍙傛暟涓嶇鍚堣鑼冿紝涓嶈兘杩涜鏌ヨ");
+        }
+        return value;
+    }
+
+    /**
+     * 楠岃瘉 order by 璇硶鏄惁绗﹀悎瑙勮寖
+     */
+    public static boolean isValidOrderBySql(String value) {
+        return value.matches(SQL_PATTERN);
+    }
+
+    /**
+     * SQL鍏抽敭瀛楁鏌�
+     */
+    public static void filterKeyword(String value) {
+        if (StringUtils.isEmpty(value)) {
+            return;
+        }
+        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
+        for (String sqlKeyword : sqlKeywords) {
+            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) {
+                throw new UtilException("鍙傛暟瀛樺湪SQL娉ㄥ叆椋庨櫓");
+            }
+        }
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/validate/AddGroup.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/AddGroup.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/validate/AddGroup.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/AddGroup.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/validate/EditGroup.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/EditGroup.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/validate/EditGroup.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/EditGroup.java
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java
rename to ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
new file mode 100644
index 0000000..35a2280
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/controller/BaseController.java
@@ -0,0 +1,40 @@
+package com.ruoyi.common.core.web.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.StringUtils;
+
+/**
+ * web灞傞�氱敤鏁版嵁澶勭悊
+ *
+ * @author Lion Li
+ */
+public class BaseController {
+
+    /**
+     * 鍝嶅簲杩斿洖缁撴灉
+     *
+     * @param rows 褰卞搷琛屾暟
+     * @return 鎿嶄綔缁撴灉
+     */
+    protected R<Void> toAjax(int rows) {
+        return rows > 0 ? R.ok() : R.fail();
+    }
+
+    /**
+     * 鍝嶅簲杩斿洖缁撴灉
+     *
+     * @param result 缁撴灉
+     * @return 鎿嶄綔缁撴灉
+     */
+    protected R<Void> toAjax(boolean result) {
+        return result ? R.ok() : R.fail();
+    }
+
+    /**
+     * 椤甸潰璺宠浆
+     */
+    public String redirect(String url) {
+        return StringUtils.format("redirect:{}", url);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/BaseEntity.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/BaseEntity.java
new file mode 100644
index 0000000..70e7588
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/BaseEntity.java
@@ -0,0 +1,65 @@
+package com.ruoyi.common.core.web.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Entity鍩虹被
+ *
+ * @author Lion Li
+ */
+
+@Data
+public class BaseEntity implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鎼滅储鍊�
+     */
+    @JsonIgnore
+    @TableField(exist = false)
+    private String searchValue;
+
+    /**
+     * 鍒涘缓鑰�
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private String createBy;
+
+    /**
+     * 鍒涘缓鏃堕棿
+     */
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+    /**
+     * 鏇存柊鑰�
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String updateBy;
+
+    /**
+     * 鏇存柊鏃堕棿
+     */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+
+    /**
+     * 璇锋眰鍙傛暟
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @TableField(exist = false)
+    private Map<String, Object> params = new HashMap<>();
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/TreeEntity.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/TreeEntity.java
new file mode 100644
index 0000000..109b7fb
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/TreeEntity.java
@@ -0,0 +1,41 @@
+package com.ruoyi.common.core.web.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree鍩虹被
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TreeEntity<T> extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鐖惰彍鍗曞悕绉�
+     */
+    @TableField(exist = false)
+    private String parentName;
+
+    /**
+     * 鐖惰彍鍗旾D
+     */
+    private Long parentId;
+
+    /**
+     * 瀛愰儴闂�
+     */
+    @TableField(exist = false)
+    private List<T> children = new ArrayList<>();
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/Xss.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/Xss.java
new file mode 100644
index 0000000..ee72bdb
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/Xss.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.core.xss;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ
+ *
+ * @author Lion Li
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
+@Constraint(validatedBy = {XssValidator.class})
+public @interface Xss {
+
+    String message() default "涓嶅厑璁镐换浣曡剼鏈繍琛�";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/XssValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/XssValidator.java
new file mode 100644
index 0000000..c6b6c6b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/xss/XssValidator.java
@@ -0,0 +1,21 @@
+package com.ruoyi.common.core.xss;
+
+import cn.hutool.core.util.ReUtil;
+import cn.hutool.http.HtmlUtil;
+
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ瀹炵幇
+ *
+ * @author Lion Li
+ */
+public class XssValidator implements ConstraintValidator<Xss, String> {
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
+        return !ReUtil.contains(HtmlUtil.RE_HTML_MARK, value);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..b421558
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,7 @@
+com.ruoyi.common.core.config.ApplicationConfig
+com.ruoyi.common.core.config.AsyncConfig
+com.ruoyi.common.core.config.JacksonConfig
+com.ruoyi.common.core.config.RuoYiConfig
+com.ruoyi.common.core.config.ThreadPoolConfig
+com.ruoyi.common.core.config.ValidatorConfig
+com.ruoyi.common.core.utils.SpringUtils
diff --git a/ruoyi-common/ruoyi-common-dict/pom.xml b/ruoyi-common/ruoyi-common-dict/pom.xml
new file mode 100644
index 0000000..fcfbbd7
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-dict/pom.xml
@@ -0,0 +1,26 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-dict</artifactId>
+
+    <description>
+        ruoyi-common-dict 瀛楀吀
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/annotation/DictDataMapper.java b/ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/annotation/DictDataMapper.java
new file mode 100644
index 0000000..c005bd7
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/annotation/DictDataMapper.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.dict.annotation;
+
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.dict.jackson.DictDataJsonSerializer;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 瀛楀吀鏁版嵁鏄犲皠娉ㄨВ
+ *
+ * @author itino
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
+@JacksonAnnotationsInside
+@JsonSerialize(using = DictDataJsonSerializer.class)
+public @interface DictDataMapper {
+
+    /**
+     * 璁剧疆瀛楀吀鐨則ype鍊� (濡�: sys_user_sex)
+     */
+    String dictType() default "";
+}
diff --git a/ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/jackson/DictDataJsonSerializer.java b/ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/jackson/DictDataJsonSerializer.java
new file mode 100644
index 0000000..f6d900b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-dict/src/main/java/com/ruoyi/common/dict/jackson/DictDataJsonSerializer.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.dict.jackson;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.ruoyi.common.core.service.DictService;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.dict.annotation.DictDataMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * 瀛楀吀鏁版嵁json搴忓垪鍖栧伐鍏�
+ *
+ * @author itino
+ */
+@Slf4j
+public class DictDataJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
+
+    private String dictType;
+
+    @Override
+    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+        try {
+            DictService dictService = SpringUtils.getBean(DictService.class);
+            if (ObjectUtil.isNotNull(dictService)) {
+                String label = dictService.getDictLabel(dictType, value);
+                gen.writeString(StringUtils.isNotBlank(label) ? label : value);
+            } else {
+                gen.writeString(value);
+            }
+        } catch (BeansException e) {
+            log.error("瀛楀吀鏁版嵁鏈煡鍒�, 閲囩敤榛樿澶勭悊 => {}", e.getMessage());
+            gen.writeString(value);
+        }
+    }
+
+    @Override
+    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
+        DictDataMapper anno = property.getAnnotation(DictDataMapper.class);
+        if (Objects.nonNull(anno) && StrUtil.isNotBlank(anno.dictType())) {
+            this.dictType = anno.dictType();
+            return this;
+        }
+        return prov.findValueSerializer(property.getType(), property);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-doc/pom.xml b/ruoyi-common/ruoyi-common-doc/pom.xml
new file mode 100644
index 0000000..45c5fed
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/pom.xml
@@ -0,0 +1,36 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-doc</artifactId>
+
+    <description>
+        ruoyi-common-doc 绯荤粺鎺ュ彛
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.therapi</groupId>
+            <artifactId>therapi-runtime-javadoc</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerConfig.java b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerConfig.java
new file mode 100644
index 0000000..ec3f776
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerConfig.java
@@ -0,0 +1,125 @@
+package com.ruoyi.common.doc.config;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.doc.config.properties.SwaggerProperties;
+import com.ruoyi.common.doc.handler.OpenApiHandler;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Paths;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import lombok.RequiredArgsConstructor;
+import org.springdoc.core.configuration.SpringDocConfiguration;
+import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
+import org.springdoc.core.customizers.OpenApiCustomizer;
+import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
+import org.springdoc.core.properties.SpringDocConfigProperties;
+import org.springdoc.core.providers.JavadocProvider;
+import org.springdoc.core.service.OpenAPIService;
+import org.springdoc.core.service.SecurityService;
+import org.springdoc.core.utils.PropertyResolverUtils;
+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.ServerProperties;
+import org.springframework.context.annotation.Bean;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Swagger 鏂囨。閰嶇疆
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@AutoConfiguration(before = SpringDocConfiguration.class)
+@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true", matchIfMissing = true)
+public class SwaggerConfig {
+
+    private final SwaggerProperties swaggerProperties;
+    private final ServerProperties serverProperties;
+
+    @Bean
+    @ConditionalOnMissingBean(OpenAPI.class)
+    public OpenAPI openApi() {
+        OpenAPI openApi = new OpenAPI();
+        // 鏂囨。鍩烘湰淇℃伅
+        SwaggerProperties.InfoProperties infoProperties = swaggerProperties.getInfo();
+        Info info = convertInfo(infoProperties);
+        openApi.info(info);
+        // 鎵╁睍鏂囨。淇℃伅
+        openApi.externalDocs(swaggerProperties.getExternalDocs());
+        openApi.tags(swaggerProperties.getTags());
+        openApi.paths(swaggerProperties.getPaths());
+        openApi.components(swaggerProperties.getComponents());
+        Set<String> keySet = swaggerProperties.getComponents().getSecuritySchemes().keySet();
+        List<SecurityRequirement> list = new ArrayList<>();
+        SecurityRequirement securityRequirement = new SecurityRequirement();
+        keySet.forEach(securityRequirement::addList);
+        list.add(securityRequirement);
+        openApi.security(list);
+
+        return openApi;
+    }
+
+    private Info convertInfo(SwaggerProperties.InfoProperties infoProperties) {
+        Info info = new Info();
+        info.setTitle(infoProperties.getTitle());
+        info.setDescription(infoProperties.getDescription());
+        info.setContact(infoProperties.getContact());
+        info.setLicense(infoProperties.getLicense());
+        info.setVersion(infoProperties.getVersion());
+        return info;
+    }
+
+    /**
+     * 鑷畾涔� openapi 澶勭悊鍣�
+     */
+    @Bean
+    public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
+                                         SecurityService securityParser,
+                                         SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
+                                         Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers,
+                                         Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider) {
+        return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider);
+    }
+
+    /**
+     * 瀵瑰凡缁忕敓鎴愬ソ鐨� OpenApi 杩涜鑷畾涔夋搷浣�
+     */
+    @Bean
+    public OpenApiCustomizer openApiCustomiser() {
+        String contextPath = serverProperties.getServlet().getContextPath();
+        String finalContextPath;
+        if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) {
+            finalContextPath = "";
+        } else {
+            finalContextPath = contextPath;
+        }
+        // 瀵规墍鏈夎矾寰勫鍔犲墠缃笂涓嬫枃璺緞
+        return openApi -> {
+            Paths oldPaths = openApi.getPaths();
+            if (oldPaths instanceof PlusPaths) {
+                return;
+            }
+            PlusPaths newPaths = new PlusPaths();
+            oldPaths.forEach((k, v) -> newPaths.addPathItem(finalContextPath + k, v));
+            openApi.setPaths(newPaths);
+        };
+    }
+
+    /**
+     * 鍗曠嫭浣跨敤涓�涓被渚夸簬鍒ゆ柇 瑙e喅springdoc璺緞鎷兼帴閲嶅闂
+     *
+     * @author Lion Li
+     */
+    static class PlusPaths extends Paths {
+
+        public PlusPaths() {
+            super();
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java
new file mode 100644
index 0000000..3af2796
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java
@@ -0,0 +1,101 @@
+package com.ruoyi.common.doc.config.properties;
+
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.ExternalDocumentation;
+import io.swagger.v3.oas.models.Paths;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.tags.Tag;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * swagger 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "swagger")
+public class SwaggerProperties {
+
+    /**
+     * 鏄惁寮�鍚� openApi 鏂囨。
+     */
+    private Boolean enabled = true;
+
+    /**
+     * 鏂囨。鍩烘湰淇℃伅
+     */
+    @NestedConfigurationProperty
+    private InfoProperties info = new InfoProperties();
+
+    /**
+     * 鎵╁睍鏂囨。鍦板潃
+     */
+    @NestedConfigurationProperty
+    private ExternalDocumentation externalDocs;
+
+    /**
+     * 鏍囩
+     */
+    private List<Tag> tags = null;
+
+    /**
+     * 璺緞
+     */
+    @NestedConfigurationProperty
+    private Paths paths = null;
+
+    /**
+     * 缁勪欢
+     */
+    @NestedConfigurationProperty
+    private Components components = null;
+
+    /**
+     * <p>
+     * 鏂囨。鐨勫熀纭�灞炴�т俊鎭�
+     * </p>
+     *
+     * @see io.swagger.v3.oas.models.info.Info
+     *
+     * 涓轰簡 springboot 鑷姩鐢熶骇閰嶇疆鎻愮ず淇℃伅锛屾墍浠ヨ繖閲屽鍒朵竴涓被鍑烘潵
+     */
+    @Data
+    public static class InfoProperties {
+
+        /**
+         * 鏍囬
+         */
+        private String title = null;
+
+        /**
+         * 鎻忚堪
+         */
+        private String description = null;
+
+        /**
+         * 鑱旂郴浜轰俊鎭�
+         */
+        @NestedConfigurationProperty
+        private Contact contact = null;
+
+        /**
+         * 璁稿彲璇�
+         */
+        @NestedConfigurationProperty
+        private License license = null;
+
+        /**
+         * 鐗堟湰
+         */
+        private String version = null;
+
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java
new file mode 100644
index 0000000..7894bf1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java
@@ -0,0 +1,252 @@
+package com.ruoyi.common.doc.handler;
+
+import cn.hutool.core.io.IoUtil;
+import io.swagger.v3.core.jackson.TypeNameResolver;
+import io.swagger.v3.core.util.AnnotationsUtils;
+import io.swagger.v3.oas.annotations.tags.Tags;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.Paths;
+import io.swagger.v3.oas.models.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
+import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
+import org.springdoc.core.properties.SpringDocConfigProperties;
+import org.springdoc.core.providers.JavadocProvider;
+import org.springdoc.core.service.OpenAPIService;
+import org.springdoc.core.service.SecurityService;
+import org.springdoc.core.utils.PropertyResolverUtils;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.method.HandlerMethod;
+
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * 鑷畾涔� openapi 澶勭悊鍣�
+ * 瀵规簮鐮佸姛鑳借繘琛屼慨鏀� 澧炲己浣跨敤
+ */
+@Slf4j
+@SuppressWarnings("all")
+public class OpenApiHandler extends OpenAPIService {
+
+    /**
+     * The Basic error controller.
+     */
+    private static Class<?> basicErrorController;
+
+    /**
+     * The Security parser.
+     */
+    private final SecurityService securityParser;
+
+    /**
+     * The Mappings map.
+     */
+    private final Map<String, Object> mappingsMap = new HashMap<>();
+
+    /**
+     * The Springdoc tags.
+     */
+    private final Map<HandlerMethod, Tag> springdocTags = new HashMap<>();
+
+    /**
+     * The Open api builder customisers.
+     */
+    private final Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers;
+
+    /**
+     * The server base URL customisers.
+     */
+    private final Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers;
+
+    /**
+     * The Spring doc config properties.
+     */
+    private final SpringDocConfigProperties springDocConfigProperties;
+
+    /**
+     * The Cached open api map.
+     */
+    private final Map<String, OpenAPI> cachedOpenAPI = new HashMap<>();
+
+    /**
+     * The Property resolver utils.
+     */
+    private final PropertyResolverUtils propertyResolverUtils;
+
+    /**
+     * The javadoc provider.
+     */
+    private final Optional<JavadocProvider> javadocProvider;
+
+    /**
+     * The Context.
+     */
+    private ApplicationContext context;
+
+    /**
+     * The Open api.
+     */
+    private OpenAPI openAPI;
+
+    /**
+     * The Is servers present.
+     */
+    private boolean isServersPresent;
+
+    /**
+     * The Server base url.
+     */
+    private String serverBaseUrl;
+
+    /**
+     * Instantiates a new Open api builder.
+     *
+     * @param openAPI                   the open api
+     * @param securityParser            the security parser
+     * @param springDocConfigProperties the spring doc config properties
+     * @param propertyResolverUtils     the property resolver utils
+     * @param openApiBuilderCustomizers the open api builder customisers
+     * @param serverBaseUrlCustomizers  the server base url customizers
+     * @param javadocProvider           the javadoc provider
+     */
+    public OpenApiHandler(Optional<OpenAPI> openAPI, SecurityService securityParser,
+                          SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
+                          Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
+                          Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
+                          Optional<JavadocProvider> javadocProvider) {
+        super(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);
+        if (openAPI.isPresent()) {
+            this.openAPI = openAPI.get();
+            if (this.openAPI.getComponents() == null)
+                this.openAPI.setComponents(new Components());
+            if (this.openAPI.getPaths() == null)
+                this.openAPI.setPaths(new Paths());
+            if (!CollectionUtils.isEmpty(this.openAPI.getServers()))
+                this.isServersPresent = true;
+        }
+        this.propertyResolverUtils = propertyResolverUtils;
+        this.securityParser = securityParser;
+        this.springDocConfigProperties = springDocConfigProperties;
+        this.openApiBuilderCustomisers = openApiBuilderCustomizers;
+        this.serverBaseUrlCustomizers = serverBaseUrlCustomizers;
+        this.javadocProvider = javadocProvider;
+        if (springDocConfigProperties.isUseFqn())
+            TypeNameResolver.std.setUseFqn(true);
+    }
+
+    @Override
+    public Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) {
+
+        Set<Tag> tags = new HashSet<>();
+        Set<String> tagsStr = new HashSet<>();
+
+        buildTagsFromMethod(handlerMethod.getMethod(), tags, tagsStr, locale);
+        buildTagsFromClass(handlerMethod.getBeanType(), tags, tagsStr, locale);
+
+        if (!CollectionUtils.isEmpty(tagsStr))
+            tagsStr = tagsStr.stream()
+                .map(str -> propertyResolverUtils.resolve(str, locale))
+                .collect(Collectors.toSet());
+
+        if (springdocTags.containsKey(handlerMethod)) {
+            io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod);
+            tagsStr.add(tag.getName());
+            if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
+                openAPI.addTagsItem(tag);
+            }
+        }
+
+        if (!CollectionUtils.isEmpty(tagsStr)) {
+            if (CollectionUtils.isEmpty(operation.getTags()))
+                operation.setTags(new ArrayList<>(tagsStr));
+            else {
+                Set<String> operationTagsSet = new HashSet<>(operation.getTags());
+                operationTagsSet.addAll(tagsStr);
+                operation.getTags().clear();
+                operation.getTags().addAll(operationTagsSet);
+            }
+        }
+
+        if (isAutoTagClasses(operation)) {
+
+
+            if (javadocProvider.isPresent()) {
+                String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType());
+                if (StringUtils.isNotBlank(description)) {
+                    io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.Tag();
+
+                    // 鑷畾涔夐儴鍒� 淇敼浣跨敤java娉ㄩ噴褰搕ag鍚�
+                    List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>());
+                    // tag.setName(tagAutoName);
+                    tag.setName(list.get(0));
+                    operation.addTagsItem(list.get(0));
+
+                    tag.setDescription(description);
+                    if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
+                        openAPI.addTagsItem(tag);
+                    }
+                }
+            } else {
+                String tagAutoName = splitCamelCase(handlerMethod.getBeanType().getSimpleName());
+                operation.addTagsItem(tagAutoName);
+            }
+        }
+
+        if (!CollectionUtils.isEmpty(tags)) {
+            // Existing tags
+            List<io.swagger.v3.oas.models.tags.Tag> openApiTags = openAPI.getTags();
+            if (!CollectionUtils.isEmpty(openApiTags))
+                tags.addAll(openApiTags);
+            openAPI.setTags(new ArrayList<>(tags));
+        }
+
+        // Handle SecurityRequirement at operation level
+        io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser
+            .getSecurityRequirements(handlerMethod);
+        if (securityRequirements != null) {
+            if (securityRequirements.length == 0)
+                operation.setSecurity(Collections.emptyList());
+            else
+                securityParser.buildSecurityRequirement(securityRequirements, operation);
+        }
+
+        return operation;
+    }
+
+    private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) {
+        // method tags
+        Set<Tags> tagsSet = AnnotatedElementUtils
+            .findAllMergedAnnotations(method, Tags.class);
+        Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream()
+            .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet());
+        methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class));
+        if (!CollectionUtils.isEmpty(methodTags)) {
+            tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet()));
+            List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags);
+            addTags(allTags, tags, locale);
+        }
+    }
+
+    private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag> tags, Locale locale) {
+        Optional<Set<io.swagger.v3.oas.models.tags.Tag>> optionalTagSet = AnnotationsUtils
+            .getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true);
+        optionalTagSet.ifPresent(tagsSet -> {
+            tagsSet.forEach(tag -> {
+                tag.name(propertyResolverUtils.resolve(tag.getName(), locale));
+                tag.description(propertyResolverUtils.resolve(tag.getDescription(), locale));
+                if (tags.stream().noneMatch(t -> t.getName().equals(tag.getName())))
+                    tags.add(tag);
+            });
+        });
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..8ae5a18
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.doc.config.SwaggerConfig
diff --git a/ruoyi-common/ruoyi-common-excel/pom.xml b/ruoyi-common/ruoyi-common-excel/pom.xml
new file mode 100644
index 0000000..e766a76
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/pom.xml
@@ -0,0 +1,31 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-excel</artifactId>
+
+    <description>
+        ruoyi-common-excel
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/CellMerge.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/CellMerge.java
new file mode 100644
index 0000000..5c0f552
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/CellMerge.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.excel.annotation;
+
+import com.ruoyi.common.excel.core.CellMergeStrategy;
+
+import java.lang.annotation.*;
+
+/**
+ * excel 鍒楀崟鍏冩牸鍚堝苟(鍚堝苟鍒楃浉鍚岄」)
+ *
+ * 闇�鎼厤 {@link CellMergeStrategy} 绛栫暐浣跨敤
+ *
+ * @author Lion Li
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface CellMerge {
+
+	/**
+	 * col index
+	 */
+	int index() default -1;
+
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/ExcelDictFormat.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/ExcelDictFormat.java
new file mode 100644
index 0000000..a9671fb
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/annotation/ExcelDictFormat.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.excel.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 瀛楀吀鏍煎紡鍖�
+ *
+ * @author Lion Li
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface ExcelDictFormat {
+
+    /**
+     * 濡傛灉鏄瓧鍏哥被鍨嬶紝璇疯缃瓧鍏哥殑type鍊� (濡�: sys_user_sex)
+     */
+    String dictType() default "";
+
+    /**
+     * 璇诲彇鍐呭杞〃杈惧紡 (濡�: 0=鐢�,1=濂�,2=鏈煡)
+     */
+    String readConverterExp() default "";
+
+    /**
+     * 鍒嗛殧绗︼紝璇诲彇瀛楃涓茬粍鍐呭
+     */
+    String separator() default ",";
+
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelBigNumberConvert.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelBigNumberConvert.java
new file mode 100644
index 0000000..1e10334
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelBigNumberConvert.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.excel.convert;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+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;
+
+import java.math.BigDecimal;
+
+/**
+ * 澶ф暟鍊艰浆鎹�
+ * Excel 鏁板�奸暱搴︿綅15浣� 澶т簬15浣嶇殑鏁板�艰浆鎹綅瀛楃涓�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class ExcelBigNumberConvert implements Converter<Long> {
+
+    @Override
+    public Class<Long> supportJavaTypeKey() {
+        return Long.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return CellDataTypeEnum.STRING;
+    }
+
+    @Override
+    public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        return Convert.toLong(cellData.getData());
+    }
+
+    @Override
+    public WriteCellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        if (ObjectUtil.isNotNull(object)) {
+            String str = Convert.toStr(object);
+            if (str.length() > 15) {
+                return new WriteCellData<>(str);
+            }
+        }
+        WriteCellData<Object> cellData = new WriteCellData<>(new BigDecimal(object));
+        cellData.setType(CellDataTypeEnum.NUMBER);
+        return cellData;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelDictConvert.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelDictConvert.java
new file mode 100644
index 0000000..43af5ee
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/convert/ExcelDictConvert.java
@@ -0,0 +1,73 @@
+package com.ruoyi.common.excel.convert;
+
+import cn.hutool.core.annotation.AnnotationUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+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 com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.core.service.DictService;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Field;
+
+/**
+ * 瀛楀吀鏍煎紡鍖栬浆鎹㈠鐞�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class ExcelDictConvert implements Converter<Object> {
+
+    @Override
+    public Class<Object> supportJavaTypeKey() {
+        return Object.class;
+    }
+
+    @Override
+    public CellDataTypeEnum supportExcelTypeKey() {
+        return null;
+    }
+
+    @Override
+    public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        ExcelDictFormat anno = getAnnotation(contentProperty.getField());
+        String type = anno.dictType();
+        String label = cellData.getStringValue();
+        String value;
+        if (StringUtils.isBlank(type)) {
+            value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
+        } else {
+            value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator());
+        }
+        return Convert.convert(contentProperty.getField().getType(), value);
+    }
+
+    @Override
+    public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+        if (ObjectUtil.isNull(object)) {
+            return new WriteCellData<>("");
+        }
+        ExcelDictFormat anno = getAnnotation(contentProperty.getField());
+        String type = anno.dictType();
+        String value = Convert.toStr(object);
+        String label;
+        if (StringUtils.isBlank(type)) {
+            label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
+        } else {
+            label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator());
+        }
+        return new WriteCellData<>(label);
+    }
+
+    private ExcelDictFormat getAnnotation(Field field) {
+        return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/CellMergeStrategy.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/CellMergeStrategy.java
new file mode 100644
index 0000000..b5bdd94
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/CellMergeStrategy.java
@@ -0,0 +1,114 @@
+package com.ruoyi.common.excel.core;
+
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.write.merge.AbstractMergeStrategy;
+import com.ruoyi.common.excel.annotation.CellMerge;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鍒楀�奸噸澶嶅悎骞剁瓥鐣�
+ *
+ * @author Lion Li
+ */
+@AllArgsConstructor
+@Slf4j
+public class CellMergeStrategy extends AbstractMergeStrategy {
+
+	private List<?> list;
+	private boolean hasTitle;
+
+	@Override
+	protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
+		List<CellRangeAddress> cellList = handle(list, hasTitle);
+		// judge the list is not null
+		if (CollectionUtils.isNotEmpty(cellList)) {
+			// the judge is necessary
+			if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) {
+				for (CellRangeAddress item : cellList) {
+					sheet.addMergedRegion(item);
+				}
+			}
+		}
+	}
+
+	@SneakyThrows
+	private static List<CellRangeAddress> handle(List<?> list, boolean hasTitle) {
+		List<CellRangeAddress> cellList = new ArrayList<>();
+		if (CollectionUtils.isEmpty(list)) {
+			return cellList;
+		}
+		Class<?> clazz = list.get(0).getClass();
+		Field[] fields = clazz.getDeclaredFields();
+		// 鏈夋敞瑙g殑瀛楁
+		List<Field> mergeFields = new ArrayList<>();
+		List<Integer> mergeFieldsIndex = new ArrayList<>();
+		for (int i = 0; i < fields.length; i++) {
+			Field field = fields[i];
+			if (field.isAnnotationPresent(CellMerge.class)) {
+				CellMerge cm = field.getAnnotation(CellMerge.class);
+				mergeFields.add(field);
+				mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index());
+			}
+		}
+		// 琛屽悎骞跺紑濮嬩笅鏍�
+		int rowIndex = hasTitle ? 1 : 0;
+		Map<Field, RepeatCell> map = new HashMap<>();
+		// 鐢熸垚涓や袱鍚堝苟鍗曞厓鏍�
+		for (int i = 0; i < list.size(); i++) {
+			for (int j = 0; j < mergeFields.size(); j++) {
+				Field field = mergeFields.get(j);
+				String name = field.getName();
+				String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
+				Method readMethod = clazz.getMethod(methodName);
+				Object val = readMethod.invoke(list.get(i));
+
+				int colNum = mergeFieldsIndex.get(j);
+				if (!map.containsKey(field)) {
+					map.put(field, new RepeatCell(val, i));
+				} else {
+					RepeatCell repeatCell = map.get(field);
+					Object cellValue = repeatCell.getValue();
+					if (cellValue == null || "".equals(cellValue)) {
+						// 绌哄�艰烦杩囦笉鍚堝苟
+						continue;
+					}
+					if (!cellValue.equals(val)) {
+						if (i - repeatCell.getCurrent() > 1) {
+							cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
+						}
+						map.put(field, new RepeatCell(val, i));
+					} else if (i == list.size() - 1) {
+						if (i > repeatCell.getCurrent()) {
+							cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
+						}
+					}
+				}
+			}
+		}
+		return cellList;
+	}
+
+	@Data
+	@AllArgsConstructor
+	static class RepeatCell {
+
+		private Object value;
+
+		private int current;
+
+	}
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefaultExcelListener.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefaultExcelListener.java
new file mode 100644
index 0000000..a94f2d0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefaultExcelListener.java
@@ -0,0 +1,106 @@
+package com.ruoyi.common.excel.core;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.exception.ExcelAnalysisException;
+import com.alibaba.excel.exception.ExcelDataConvertException;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.ValidatorUtils;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Excel 瀵煎叆鐩戝惉
+ *
+ * @author Yjoioooo
+ * @author Lion Li
+ */
+@Slf4j
+@NoArgsConstructor
+public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {
+
+    /**
+     * 鏄惁Validator妫�楠岋紝榛樿涓烘槸
+     */
+    private Boolean isValidate = Boolean.TRUE;
+
+    /**
+     * excel 琛ㄥご鏁版嵁
+     */
+    private Map<Integer, String> headMap;
+
+    /**
+     * 瀵煎叆鍥炴墽
+     */
+    private ExcelResult<T> excelResult;
+
+    public DefaultExcelListener(boolean isValidate) {
+        this.excelResult = new DefautExcelResult<>();
+        this.isValidate = isValidate;
+    }
+
+    /**
+     * 澶勭悊寮傚父
+     *
+     * @param exception ExcelDataConvertException
+     * @param context   Excel 涓婁笅鏂�
+     */
+    @Override
+    public void onException(Exception exception, AnalysisContext context) throws Exception {
+        String errMsg = null;
+        if (exception instanceof ExcelDataConvertException) {
+            // 濡傛灉鏄煇涓�涓崟鍏冩牸鐨勮浆鎹㈠紓甯� 鑳借幏鍙栧埌鍏蜂綋琛屽彿
+            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
+            Integer rowIndex = excelDataConvertException.getRowIndex();
+            Integer columnIndex = excelDataConvertException.getColumnIndex();
+            errMsg = StrUtil.format("绗瑊}琛�-绗瑊}鍒�-琛ㄥご{}: 瑙f瀽寮傚父<br/>",
+                rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));
+            if (log.isDebugEnabled()) {
+                log.error(errMsg);
+            }
+        }
+        if (exception instanceof ConstraintViolationException) {
+            ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
+            Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
+            String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", ");
+            errMsg = StrUtil.format("绗瑊}琛屾暟鎹牎楠屽紓甯�: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);
+            if (log.isDebugEnabled()) {
+                log.error(errMsg);
+            }
+        }
+        excelResult.getErrorList().add(errMsg);
+        throw new ExcelAnalysisException(errMsg);
+    }
+
+    @Override
+    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
+        this.headMap = headMap;
+        log.debug("瑙f瀽鍒颁竴鏉¤〃澶存暟鎹�: {}", JsonUtils.toJsonString(headMap));
+    }
+
+    @Override
+    public void invoke(T data, AnalysisContext context) {
+        if (isValidate) {
+            ValidatorUtils.validate(data);
+        }
+        excelResult.getList().add(data);
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        log.debug("鎵�鏈夋暟鎹В鏋愬畬鎴愶紒");
+    }
+
+    @Override
+    public ExcelResult<T> getExcelResult() {
+        return excelResult;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefautExcelResult.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefautExcelResult.java
new file mode 100644
index 0000000..af678ef
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/DefautExcelResult.java
@@ -0,0 +1,73 @@
+package com.ruoyi.common.excel.core;
+
+import cn.hutool.core.util.StrUtil;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 榛樿excel杩斿洖瀵硅薄
+ *
+ * @author Yjoioooo
+ * @author Lion Li
+ */
+public class DefautExcelResult<T> implements ExcelResult<T> {
+
+    /**
+     * 鏁版嵁瀵硅薄list
+     */
+    @Setter
+    private List<T> list;
+
+    /**
+     * 閿欒淇℃伅鍒楄〃
+     */
+    @Setter
+    private List<String> errorList;
+
+    public DefautExcelResult() {
+        this.list = new ArrayList<>();
+        this.errorList = new ArrayList<>();
+    }
+
+    public DefautExcelResult(List<T> list, List<String> errorList) {
+        this.list = list;
+        this.errorList = errorList;
+    }
+
+    public DefautExcelResult(ExcelResult<T> excelResult) {
+        this.list = excelResult.getList();
+        this.errorList = excelResult.getErrorList();
+    }
+
+    @Override
+    public List<T> getList() {
+        return list;
+    }
+
+    @Override
+    public List<String> getErrorList() {
+        return errorList;
+    }
+
+    /**
+     * 鑾峰彇瀵煎叆鍥炴墽
+     *
+     * @return 瀵煎叆鍥炴墽
+     */
+    @Override
+    public String getAnalysis() {
+        int successCount = list.size();
+        int errorCount = errorList.size();
+        if (successCount == 0) {
+            return "璇诲彇澶辫触锛屾湭瑙f瀽鍒版暟鎹�";
+        } else {
+            if (errorCount == 0) {
+                return StrUtil.format("鎭枩鎮紝鍏ㄩ儴璇诲彇鎴愬姛锛佸叡{}鏉�", successCount);
+            } else {
+                return "";
+            }
+        }
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelListener.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelListener.java
new file mode 100644
index 0000000..093b94f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelListener.java
@@ -0,0 +1,14 @@
+package com.ruoyi.common.excel.core;
+
+import com.alibaba.excel.read.listener.ReadListener;
+
+/**
+ * Excel 瀵煎叆鐩戝惉
+ *
+ * @author Lion Li
+ */
+public interface ExcelListener<T> extends ReadListener<T> {
+
+    ExcelResult<T> getExcelResult();
+
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelResult.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelResult.java
new file mode 100644
index 0000000..81aab5d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/core/ExcelResult.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.excel.core;
+
+import java.util.List;
+
+/**
+ * excel杩斿洖瀵硅薄
+ *
+ * @author Lion Li
+ */
+public interface ExcelResult<T> {
+
+    /**
+     * 瀵硅薄鍒楄〃
+     */
+    List<T> getList();
+
+    /**
+     * 閿欒鍒楄〃
+     */
+    List<String> getErrorList();
+
+    /**
+     * 瀵煎叆鍥炴墽
+     */
+    String getAnalysis();
+}
diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/utils/ExcelUtil.java b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/utils/ExcelUtil.java
new file mode 100644
index 0000000..dbe3ae7
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-excel/src/main/java/com/ruoyi/common/excel/utils/ExcelUtil.java
@@ -0,0 +1,328 @@
+package com.ruoyi.common.excel.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.resource.ClassPathResource;
+import cn.hutool.core.util.IdUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.metadata.fill.FillConfig;
+import com.alibaba.excel.write.metadata.fill.FillWrapper;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.file.FileUtils;
+import com.ruoyi.common.excel.convert.ExcelBigNumberConvert;
+import com.ruoyi.common.excel.core.CellMergeStrategy;
+import com.ruoyi.common.excel.core.DefaultExcelListener;
+import com.ruoyi.common.excel.core.ExcelListener;
+import com.ruoyi.common.excel.core.ExcelResult;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import jakarta.servlet.ServletOutputStream;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Excel鐩稿叧澶勭悊
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class ExcelUtil {
+
+    /**
+     * 鍚屾瀵煎叆(閫傜敤浜庡皬鏁版嵁閲�)
+     *
+     * @param is 杈撳叆娴�
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public static <T> List<T> importExcel(InputStream is, Class<T> clazz) {
+        return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync();
+    }
+
+
+    /**
+     * 浣跨敤鏍¢獙鐩戝惉鍣� 寮傛瀵煎叆 鍚屾杩斿洖
+     *
+     * @param is         杈撳叆娴�
+     * @param clazz      瀵硅薄绫诲瀷
+     * @param isValidate 鏄惁 Validator 妫�楠� 榛樿涓烘槸
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, boolean isValidate) {
+        DefaultExcelListener<T> listener = new DefaultExcelListener<>(isValidate);
+        EasyExcel.read(is, clazz, listener).sheet().doRead();
+        return listener.getExcelResult();
+    }
+
+    /**
+     * 浣跨敤鑷畾涔夌洃鍚櫒 寮傛瀵煎叆 鑷畾涔夎繑鍥�
+     *
+     * @param is       杈撳叆娴�
+     * @param clazz    瀵硅薄绫诲瀷
+     * @param listener 鑷畾涔夌洃鍚櫒
+     * @return 杞崲鍚庨泦鍚�
+     */
+    public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) {
+        EasyExcel.read(is, clazz, listener).sheet().doRead();
+        return listener.getExcelResult();
+    }
+
+    /**
+     * 瀵煎嚭excel
+     *
+     * @param list      瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param clazz     瀹炰綋绫�
+     * @param response  鍝嶅簲浣�
+     */
+    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
+        try {
+            resetResponse(sheetName, response);
+            ServletOutputStream os = response.getOutputStream();
+            exportExcel(list, sheetName, clazz, false, os);
+        } catch (IOException e) {
+            throw new RuntimeException("瀵煎嚭Excel寮傚父");
+        }
+    }
+
+    /**
+     * 瀵煎嚭excel
+     *
+     * @param list      瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param clazz     瀹炰綋绫�
+     * @param merge     鏄惁鍚堝苟鍗曞厓鏍�
+     * @param response  鍝嶅簲浣�
+     */
+    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response) {
+        try {
+            resetResponse(sheetName, response);
+            ServletOutputStream os = response.getOutputStream();
+            exportExcel(list, sheetName, clazz, merge, os);
+        } catch (IOException e) {
+            throw new RuntimeException("瀵煎嚭Excel寮傚父");
+        }
+    }
+
+    /**
+     * 瀵煎嚭excel
+     *
+     * @param list      瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param clazz     瀹炰綋绫�
+     * @param os        杈撳嚭娴�
+     */
+    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) {
+        exportExcel(list, sheetName, clazz, false, os);
+    }
+
+    /**
+     * 瀵煎嚭excel
+     *
+     * @param list      瀵煎嚭鏁版嵁闆嗗悎
+     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+     * @param clazz     瀹炰綋绫�
+     * @param merge     鏄惁鍚堝苟鍗曞厓鏍�
+     * @param os        杈撳嚭娴�
+     */
+    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os) {
+        ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
+            .autoCloseStream(false)
+            // 鑷姩閫傞厤
+            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+            // 澶ф暟鍊艰嚜鍔ㄨ浆鎹� 闃叉澶辩湡
+            .registerConverter(new ExcelBigNumberConvert())
+            .sheet(sheetName);
+        if (merge) {
+            // 鍚堝苟澶勭悊鍣�
+            builder.registerWriteHandler(new CellMergeStrategy(list, true));
+        }
+        builder.doWrite(list);
+    }
+
+    /**
+     * 鍗曡〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {.灞炴�
+     *
+     * @param filename     鏂囦欢鍚�
+     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
+     *                     渚嬪: excel/temp.xlsx
+     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
+     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
+     * @param response     鍝嶅簲浣�
+     */
+    public static void exportTemplate(List<Object> data, String filename, String templatePath, HttpServletResponse response) {
+        try {
+            resetResponse(filename, response);
+            ServletOutputStream os = response.getOutputStream();
+            exportTemplate(data, templatePath, os);
+        } catch (IOException e) {
+            throw new RuntimeException("瀵煎嚭Excel寮傚父");
+        }
+    }
+
+    /**
+     * 鍗曡〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {.灞炴�
+     *
+     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
+     *                     渚嬪: excel/temp.xlsx
+     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
+     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
+     * @param os           杈撳嚭娴�
+     */
+    public static void exportTemplate(List<Object> data, String templatePath, OutputStream os) {
+        ClassPathResource templateResource = new ClassPathResource(templatePath);
+        ExcelWriter excelWriter = EasyExcel.write(os)
+            .withTemplate(templateResource.getStream())
+            .autoCloseStream(false)
+            // 澶ф暟鍊艰嚜鍔ㄨ浆鎹� 闃叉澶辩湡
+            .registerConverter(new ExcelBigNumberConvert())
+            .build();
+        WriteSheet writeSheet = EasyExcel.writerSheet().build();
+        if (CollUtil.isEmpty(data)) {
+            throw new IllegalArgumentException("鏁版嵁涓虹┖");
+        }
+        // 鍗曡〃澶氭暟鎹鍑� 妯℃澘鏍煎紡涓� {.灞炴�
+        for (Object d : data) {
+            excelWriter.fill(d, writeSheet);
+        }
+        excelWriter.finish();
+    }
+
+    /**
+     * 澶氳〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {key.灞炴�
+     *
+     * @param filename     鏂囦欢鍚�
+     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
+     *                     渚嬪: excel/temp.xlsx
+     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
+     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
+     * @param response     鍝嶅簲浣�
+     */
+    public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) {
+        try {
+            resetResponse(filename, response);
+            ServletOutputStream os = response.getOutputStream();
+            exportTemplateMultiList(data, templatePath, os);
+        } catch (IOException e) {
+            throw new RuntimeException("瀵煎嚭Excel寮傚父");
+        }
+    }
+
+    /**
+     * 澶氳〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {key.灞炴�
+     *
+     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
+     *                     渚嬪: excel/temp.xlsx
+     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
+     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
+     * @param os           杈撳嚭娴�
+     */
+    public static void exportTemplateMultiList(Map<String, Object> data, String templatePath, OutputStream os) {
+        ClassPathResource templateResource = new ClassPathResource(templatePath);
+        ExcelWriter excelWriter = EasyExcel.write(os)
+            .withTemplate(templateResource.getStream())
+            .autoCloseStream(false)
+            // 澶ф暟鍊艰嚜鍔ㄨ浆鎹� 闃叉澶辩湡
+            .registerConverter(new ExcelBigNumberConvert())
+            .build();
+        WriteSheet writeSheet = EasyExcel.writerSheet().build();
+        if (CollUtil.isEmpty(data)) {
+            throw new IllegalArgumentException("鏁版嵁涓虹┖");
+        }
+        for (Map.Entry<String, Object> map : data.entrySet()) {
+            // 璁剧疆鍒楄〃鍚庣画杩樻湁鏁版嵁
+            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
+            if (map.getValue() instanceof Collection) {
+                // 澶氳〃瀵煎嚭蹇呴』浣跨敤 FillWrapper
+                excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
+            } else {
+                excelWriter.fill(map.getValue(), writeSheet);
+            }
+        }
+        excelWriter.finish();
+    }
+
+    /**
+     * 閲嶇疆鍝嶅簲浣�
+     */
+    private static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException {
+        String filename = encodingFilename(sheetName);
+        FileUtils.setAttachmentResponseHeader(response, filename);
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
+    }
+
+    /**
+     * 瑙f瀽瀵煎嚭鍊� 0=鐢�,1=濂�,2=鏈煡
+     *
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp  缈昏瘧娉ㄨВ
+     * @param separator     鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String convertByExp(String propertyValue, String converterExp, String separator) {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource) {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator)) {
+                for (String value : propertyValue.split(separator)) {
+                    if (itemArray[0].equals(value)) {
+                        propertyString.append(itemArray[1] + separator);
+                        break;
+                    }
+                }
+            } else {
+                if (itemArray[0].equals(propertyValue)) {
+                    return itemArray[1];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 鍙嶅悜瑙f瀽鍊� 鐢�=0,濂�=1,鏈煡=2
+     *
+     * @param propertyValue 鍙傛暟鍊�
+     * @param converterExp  缈昏瘧娉ㄨВ
+     * @param separator     鍒嗛殧绗�
+     * @return 瑙f瀽鍚庡��
+     */
+    public static String reverseByExp(String propertyValue, String converterExp, String separator) {
+        StringBuilder propertyString = new StringBuilder();
+        String[] convertSource = converterExp.split(",");
+        for (String item : convertSource) {
+            String[] itemArray = item.split("=");
+            if (StringUtils.containsAny(propertyValue, separator)) {
+                for (String value : propertyValue.split(separator)) {
+                    if (itemArray[1].equals(value)) {
+                        propertyString.append(itemArray[0] + separator);
+                        break;
+                    }
+                }
+            } else {
+                if (itemArray[1].equals(propertyValue)) {
+                    return itemArray[0];
+                }
+            }
+        }
+        return StringUtils.stripEnd(propertyString.toString(), separator);
+    }
+
+    /**
+     * 缂栫爜鏂囦欢鍚�
+     */
+    public static String encodingFilename(String filename) {
+        return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-idempotent/pom.xml b/ruoyi-common/ruoyi-common-idempotent/pom.xml
new file mode 100644
index 0000000..8a400aa
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-idempotent/pom.xml
@@ -0,0 +1,42 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-idempotent</artifactId>
+
+    <description>
+        ruoyi-common-idempotent 骞傜瓑鍔熻兘
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-crypto</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-core</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/annotation/RepeatSubmit.java b/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/annotation/RepeatSubmit.java
new file mode 100644
index 0000000..8801e49
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/annotation/RepeatSubmit.java
@@ -0,0 +1,29 @@
+package com.ruoyi.common.idempotent.annotation;
+
+import java.lang.annotation.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
+ *
+ * @author Lion Li
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit {
+
+    /**
+     * 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦
+     */
+    int interval() default 5000;
+
+    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
+
+    /**
+     * 鎻愮ず娑堟伅 鏀寔鍥介檯鍖� 鏍煎紡涓� {code}
+     */
+    String message() default "{repeat.submit.message}";
+
+}
diff --git a/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/aspectj/RepeatSubmitAspect.java b/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/aspectj/RepeatSubmitAspect.java
new file mode 100644
index 0000000..b5d3564
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/aspectj/RepeatSubmitAspect.java
@@ -0,0 +1,153 @@
+package com.ruoyi.common.idempotent.aspectj;
+
+import cn.dev33.satoken.SaManager;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.crypto.SecureUtil;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.idempotent.annotation.RepeatSubmit;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.time.Duration;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 闃叉閲嶅鎻愪氦(鍙傝�冪編鍥TIS闃查噸绯荤粺)
+ *
+ * @author Lion Li
+ */
+@Aspect
+public class RepeatSubmitAspect {
+
+    private static final ThreadLocal<String> KEY_CACHE = new ThreadLocal<>();
+
+    @Before("@annotation(repeatSubmit)")
+    public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
+        // 濡傛灉娉ㄨВ涓嶄负0 鍒欎娇鐢ㄦ敞瑙f暟鍊�
+        long interval = 0;
+        if (repeatSubmit.interval() > 0) {
+            interval = repeatSubmit.timeUnit().toMillis(repeatSubmit.interval());
+        }
+        if (interval < 1000) {
+            throw new ServiceException("閲嶅鎻愪氦闂撮殧鏃堕棿涓嶈兘灏忎簬'1'绉�");
+        }
+        HttpServletRequest request = ServletUtils.getRequest();
+        String nowParams = argsArrayToString(point.getArgs());
+
+        // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
+        String url = request.getRequestURI();
+
+        // 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
+        String submitKey = StringUtils.trimToEmpty(request.getHeader(SaManager.getConfig().getTokenName()));
+
+        submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
+        // 鍞竴鏍囪瘑锛堟寚瀹歬ey + url + 娑堟伅澶达級
+        String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
+        String key = RedisUtils.getCacheObject(cacheRepeatKey);
+        if (key == null) {
+            RedisUtils.setCacheObject(cacheRepeatKey, "", Duration.ofMillis(interval));
+            KEY_CACHE.set(cacheRepeatKey);
+        } else {
+            String message = repeatSubmit.message();
+            if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) {
+                message = MessageUtils.message(StringUtils.substring(message, 1, message.length() - 1));
+            }
+            throw new ServiceException(message);
+        }
+    }
+
+    /**
+     * 澶勭悊瀹岃姹傚悗鎵ц
+     *
+     * @param joinPoint 鍒囩偣
+     */
+    @AfterReturning(pointcut = "@annotation(repeatSubmit)", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Object jsonResult) {
+        if (jsonResult instanceof R) {
+            try {
+                R<?> r = (R<?>) jsonResult;
+                // 鎴愬姛鍒欎笉鍒犻櫎redis鏁版嵁 淇濊瘉鍦ㄦ湁鏁堟椂闂村唴鏃犳硶閲嶅鎻愪氦
+                if (r.getCode() == R.SUCCESS) {
+                    return;
+                }
+                RedisUtils.deleteObject(KEY_CACHE.get());
+            } finally {
+                KEY_CACHE.remove();
+            }
+        }
+    }
+
+    /**
+     * 鎷︽埅寮傚父鎿嶄綔
+     *
+     * @param joinPoint 鍒囩偣
+     * @param e         寮傚父
+     */
+    @AfterThrowing(value = "@annotation(repeatSubmit)", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Exception e) {
+        RedisUtils.deleteObject(KEY_CACHE.get());
+        KEY_CACHE.remove();
+    }
+
+    /**
+     * 鍙傛暟鎷艰
+     */
+    private String argsArrayToString(Object[] paramsArray) {
+        StringBuilder params = new StringBuilder();
+        if (paramsArray != null && paramsArray.length > 0) {
+            for (Object o : paramsArray) {
+                if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {
+                    try {
+                        params.append(JsonUtils.toJsonString(o)).append(" ");
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+        return params.toString().trim();
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁闇�瑕佽繃婊ょ殑瀵硅薄銆�
+     *
+     * @param o 瀵硅薄淇℃伅銆�
+     * @return 濡傛灉鏄渶瑕佽繃婊ょ殑瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆�
+     */
+    @SuppressWarnings("rawtypes")
+    public boolean isFilterObject(final Object o) {
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray()) {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        } else if (Collection.class.isAssignableFrom(clazz)) {
+            Collection collection = (Collection) o;
+            for (Object value : collection) {
+                return value instanceof MultipartFile;
+            }
+        } else if (Map.class.isAssignableFrom(clazz)) {
+            Map map = (Map) o;
+            for (Object value : map.entrySet()) {
+                Map.Entry entry = (Map.Entry) value;
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+            || o instanceof BindingResult;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/config/IdempotentConfig.java b/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/config/IdempotentConfig.java
new file mode 100644
index 0000000..79f8d14
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-idempotent/src/main/java/com/ruoyi/common/idempotent/config/IdempotentConfig.java
@@ -0,0 +1,21 @@
+package com.ruoyi.common.idempotent.config;
+
+import com.ruoyi.common.idempotent.aspectj.RepeatSubmitAspect;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.redis.connection.RedisConfiguration;
+
+/**
+ * 骞傜瓑鍔熻兘閰嶇疆
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration(after = RedisConfiguration.class)
+public class IdempotentConfig {
+
+    @Bean
+    public RepeatSubmitAspect repeatSubmitAspect() {
+        return new RepeatSubmitAspect();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-idempotent/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-idempotent/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..3541517
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-idempotent/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.idempotent.config.IdempotentConfig
diff --git a/ruoyi-common/ruoyi-common-log/pom.xml b/ruoyi-common/ruoyi-common-log/pom.xml
new file mode 100644
index 0000000..e89a283
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/pom.xml
@@ -0,0 +1,26 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-log</artifactId>
+
+    <description>
+        ruoyi-common-log 鏃ュ織璁板綍
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-satoken</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/annotation/Log.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/annotation/Log.java
new file mode 100644
index 0000000..fb79861
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/annotation/Log.java
@@ -0,0 +1,41 @@
+package com.ruoyi.common.log.annotation;
+
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.log.enums.OperatorType;
+
+import java.lang.annotation.*;
+
+/**
+ * 鑷畾涔夋搷浣滄棩蹇楄褰曟敞瑙�
+ *
+ * @author ruoyi
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log {
+    /**
+     * 妯″潡
+     */
+    String title() default "";
+
+    /**
+     * 鍔熻兘
+     */
+    BusinessType businessType() default BusinessType.OTHER;
+
+    /**
+     * 鎿嶄綔浜虹被鍒�
+     */
+    OperatorType operatorType() default OperatorType.MANAGE;
+
+    /**
+     * 鏄惁淇濆瓨璇锋眰鐨勫弬鏁�
+     */
+    boolean isSaveRequestData() default true;
+
+    /**
+     * 鏄惁淇濆瓨鍝嶅簲鐨勫弬鏁�
+     */
+    boolean isSaveResponseData() default true;
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java
new file mode 100644
index 0000000..62f4b36
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java
@@ -0,0 +1,192 @@
+package com.ruoyi.common.log.aspect;
+
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.log.enums.BusinessStatus;
+import com.ruoyi.common.log.event.OperLogEvent;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.http.HttpMethod;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍澶勭悊
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@Aspect
+@AutoConfiguration
+public class LogAspect {
+
+    /**
+     * 鎺掗櫎鏁忔劅灞炴�у瓧娈�
+     */
+    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
+
+    /**
+     * 澶勭悊瀹岃姹傚悗鎵ц
+     *
+     * @param joinPoint 鍒囩偣
+     */
+    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
+        handleLog(joinPoint, controllerLog, null, jsonResult);
+    }
+
+    /**
+     * 鎷︽埅寮傚父鎿嶄綔
+     *
+     * @param joinPoint 鍒囩偣
+     * @param e         寮傚父
+     */
+    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
+        handleLog(joinPoint, controllerLog, e, null);
+    }
+
+    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
+        try {
+
+            // *========鏁版嵁搴撴棩蹇�=========*//
+            OperLogEvent operLog = new OperLogEvent();
+            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+            // 璇锋眰鐨勫湴鍧�
+            String ip = ServletUtils.getClientIP();
+            operLog.setOperIp(ip);
+            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
+            operLog.setOperName(LoginHelper.getUsername());
+
+            if (e != null) {
+                operLog.setStatus(BusinessStatus.FAIL.ordinal());
+                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
+            }
+            // 璁剧疆鏂规硶鍚嶇О
+            String className = joinPoint.getTarget().getClass().getName();
+            String methodName = joinPoint.getSignature().getName();
+            operLog.setMethod(className + "." + methodName + "()");
+            // 璁剧疆璇锋眰鏂瑰紡
+            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
+            // 澶勭悊璁剧疆娉ㄨВ涓婄殑鍙傛暟
+            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
+            // 鍙戝竷浜嬩欢淇濆瓨鏁版嵁搴�
+            SpringUtils.context().publishEvent(operLog);
+        } catch (Exception exp) {
+            // 璁板綍鏈湴寮傚父鏃ュ織
+            log.error("寮傚父淇℃伅:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+    }
+
+    /**
+     * 鑾峰彇娉ㄨВ涓鏂规硶鐨勬弿杩颁俊鎭� 鐢ㄤ簬Controller灞傛敞瑙�
+     *
+     * @param log     鏃ュ織
+     * @param operLog 鎿嶄綔鏃ュ織
+     * @throws Exception
+     */
+    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception {
+        // 璁剧疆action鍔ㄤ綔
+        operLog.setBusinessType(log.businessType().ordinal());
+        // 璁剧疆鏍囬
+        operLog.setTitle(log.title());
+        // 璁剧疆鎿嶄綔浜虹被鍒�
+        operLog.setOperatorType(log.operatorType().ordinal());
+        // 鏄惁闇�瑕佷繚瀛榬equest锛屽弬鏁板拰鍊�
+        if (log.isSaveRequestData()) {
+            // 鑾峰彇鍙傛暟鐨勪俊鎭紝浼犲叆鍒版暟鎹簱涓��
+            setRequestValue(joinPoint, operLog);
+        }
+        // 鏄惁闇�瑕佷繚瀛榬esponse锛屽弬鏁板拰鍊�
+        if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) {
+            operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 2000));
+        }
+    }
+
+    /**
+     * 鑾峰彇璇锋眰鐨勫弬鏁帮紝鏀惧埌log涓�
+     *
+     * @param operLog 鎿嶄綔鏃ュ織
+     * @throws Exception 寮傚父
+     */
+    private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception {
+        String requestMethod = operLog.getRequestMethod();
+        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
+            String params = argsArrayToString(joinPoint.getArgs());
+            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+        } else {
+            Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
+            MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES);
+            operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000));
+        }
+    }
+
+    /**
+     * 鍙傛暟鎷艰
+     */
+    private String argsArrayToString(Object[] paramsArray) {
+        StringBuilder params = new StringBuilder();
+        if (paramsArray != null && paramsArray.length > 0) {
+            for (Object o : paramsArray) {
+                if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {
+                    try {
+                        String str = JsonUtils.toJsonString(o);
+                        Dict dict = JsonUtils.parseMap(str);
+                        if (MapUtil.isNotEmpty(dict)) {
+                            MapUtil.removeAny(dict, EXCLUDE_PROPERTIES);
+                            str = JsonUtils.toJsonString(dict);
+                        }
+                        params.append(str).append(" ");
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+        return params.toString().trim();
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁闇�瑕佽繃婊ょ殑瀵硅薄銆�
+     *
+     * @param o 瀵硅薄淇℃伅銆�
+     * @return 濡傛灉鏄渶瑕佽繃婊ょ殑瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆�
+     */
+    @SuppressWarnings("rawtypes")
+    public boolean isFilterObject(final Object o) {
+        Class<?> clazz = o.getClass();
+        if (clazz.isArray()) {
+            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+        } else if (Collection.class.isAssignableFrom(clazz)) {
+            Collection collection = (Collection) o;
+            for (Object value : collection) {
+                return value instanceof MultipartFile;
+            }
+        } else if (Map.class.isAssignableFrom(clazz)) {
+            Map map = (Map) o;
+            for (Object value : map.entrySet()) {
+                Map.Entry entry = (Map.Entry) value;
+                return entry.getValue() instanceof MultipartFile;
+            }
+        }
+        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+            || o instanceof BindingResult;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessStatus.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessStatus.java
new file mode 100644
index 0000000..716c4cc
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessStatus.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.log.enums;
+
+/**
+ * 鎿嶄綔鐘舵��
+ *
+ * @author ruoyi
+ */
+public enum BusinessStatus {
+    /**
+     * 鎴愬姛
+     */
+    SUCCESS,
+
+    /**
+     * 澶辫触
+     */
+    FAIL,
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessType.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessType.java
new file mode 100644
index 0000000..7314de5
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/BusinessType.java
@@ -0,0 +1,58 @@
+package com.ruoyi.common.log.enums;
+
+/**
+ * 涓氬姟鎿嶄綔绫诲瀷
+ *
+ * @author ruoyi
+ */
+public enum BusinessType {
+    /**
+     * 鍏跺畠
+     */
+    OTHER,
+
+    /**
+     * 鏂板
+     */
+    INSERT,
+
+    /**
+     * 淇敼
+     */
+    UPDATE,
+
+    /**
+     * 鍒犻櫎
+     */
+    DELETE,
+
+    /**
+     * 鎺堟潈
+     */
+    GRANT,
+
+    /**
+     * 瀵煎嚭
+     */
+    EXPORT,
+
+    /**
+     * 瀵煎叆
+     */
+    IMPORT,
+
+    /**
+     * 寮洪��
+     */
+    FORCE,
+
+    /**
+     * 鐢熸垚浠g爜
+     */
+    GENCODE,
+
+    /**
+     * 娓呯┖鏁版嵁
+     */
+    CLEAN,
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/OperatorType.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/OperatorType.java
new file mode 100644
index 0000000..a93394a
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/enums/OperatorType.java
@@ -0,0 +1,23 @@
+package com.ruoyi.common.log.enums;
+
+/**
+ * 鎿嶄綔浜虹被鍒�
+ *
+ * @author ruoyi
+ */
+public enum OperatorType {
+    /**
+     * 鍏跺畠
+     */
+    OTHER,
+
+    /**
+     * 鍚庡彴鐢ㄦ埛
+     */
+    MANAGE,
+
+    /**
+     * 鎵嬫満绔敤鎴�
+     */
+    MOBILE
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/LogininforEvent.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/LogininforEvent.java
new file mode 100644
index 0000000..e52e102
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/LogininforEvent.java
@@ -0,0 +1,47 @@
+package com.ruoyi.common.log.event;
+
+import lombok.Data;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 鐧诲綍浜嬩欢
+ *
+ * @author Lion Li
+ */
+
+@Data
+public class LogininforEvent implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鐢ㄦ埛璐﹀彿
+     */
+    private String username;
+
+    /**
+     * 鐧诲綍鐘舵�� 0鎴愬姛 1澶辫触
+     */
+    private String status;
+
+    /**
+     * 鎻愮ず娑堟伅
+     */
+    private String message;
+
+    /**
+     * 璇锋眰浣�
+     */
+    private HttpServletRequest request;
+
+    /**
+     * 鍏朵粬鍙傛暟
+     */
+    private Object[] args;
+
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/OperLogEvent.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/OperLogEvent.java
new file mode 100644
index 0000000..be07dd0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/event/OperLogEvent.java
@@ -0,0 +1,106 @@
+package com.ruoyi.common.log.event;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 鎿嶄綔鏃ュ織浜嬩欢
+ *
+ * @author Lion Li
+ */
+
+@Data
+public class OperLogEvent implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鏃ュ織涓婚敭
+     */
+    private Long operId;
+
+    /**
+     * 鎿嶄綔妯″潡
+     */
+    private String title;
+
+    /**
+     * 涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛�
+     */
+    private Integer businessType;
+
+    /**
+     * 涓氬姟绫诲瀷鏁扮粍
+     */
+    private Integer[] businessTypes;
+
+    /**
+     * 璇锋眰鏂规硶
+     */
+    private String method;
+
+    /**
+     * 璇锋眰鏂瑰紡
+     */
+    private String requestMethod;
+
+    /**
+     * 鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級
+     */
+    private Integer operatorType;
+
+    /**
+     * 鎿嶄綔浜哄憳
+     */
+    private String operName;
+
+    /**
+     * 閮ㄩ棬鍚嶇О
+     */
+    private String deptName;
+
+    /**
+     * 璇锋眰url
+     */
+    private String operUrl;
+
+    /**
+     * 鎿嶄綔鍦板潃
+     */
+    private String operIp;
+
+    /**
+     * 鎿嶄綔鍦扮偣
+     */
+    private String operLocation;
+
+    /**
+     * 璇锋眰鍙傛暟
+     */
+    private String operParam;
+
+    /**
+     * 杩斿洖鍙傛暟
+     */
+    private String jsonResult;
+
+    /**
+     * 鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛�
+     */
+    private Integer status;
+
+    /**
+     * 閿欒娑堟伅
+     */
+    private String errorMsg;
+
+    /**
+     * 鎿嶄綔鏃堕棿
+     */
+    private Date operTime;
+
+}
diff --git a/ruoyi-common/ruoyi-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..b8e3223
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.log.aspect.LogAspect
diff --git a/ruoyi-common/ruoyi-common-mail/pom.xml b/ruoyi-common/ruoyi-common-mail/pom.xml
new file mode 100644
index 0000000..17d80d8
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mail/pom.xml
@@ -0,0 +1,31 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-mail</artifactId>
+
+    <description>
+        ruoyi-common-mail 閭欢妯″潡
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.mail</groupId>
+            <artifactId>jakarta.mail-api</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/MailConfig.java b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/MailConfig.java
new file mode 100644
index 0000000..44a95b6
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/MailConfig.java
@@ -0,0 +1,37 @@
+package com.ruoyi.common.mail.config;
+
+import cn.hutool.extra.mail.MailAccount;
+import com.ruoyi.common.mail.config.properties.MailProperties;
+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;
+
+/**
+ * JavaMail 閰嶇疆
+ *
+ * @author Michelle.Chung
+ */
+@AutoConfiguration
+@ConditionalOnProperty(value = "mail.enabled", havingValue = "true")
+@EnableConfigurationProperties(MailProperties.class)
+public class MailConfig {
+
+    @Bean
+    public MailAccount mailAccount(MailProperties mailProperties) {
+        MailAccount account = new MailAccount();
+        account.setHost(mailProperties.getHost());
+        account.setPort(mailProperties.getPort());
+        account.setAuth(mailProperties.getAuth());
+        account.setFrom(mailProperties.getFrom());
+        account.setUser(mailProperties.getUser());
+        account.setPass(mailProperties.getPass());
+        account.setSocketFactoryPort(mailProperties.getPort());
+        account.setStarttlsEnable(mailProperties.getStarttlsEnable());
+        account.setSslEnable(mailProperties.getSslEnable());
+        account.setTimeout(mailProperties.getTimeout());
+        account.setConnectionTimeout(mailProperties.getConnectionTimeout());
+        return account;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/properties/MailProperties.java b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/properties/MailProperties.java
new file mode 100644
index 0000000..4472fff
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/config/properties/MailProperties.java
@@ -0,0 +1,71 @@
+package com.ruoyi.common.mail.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * JavaMail 閰嶇疆灞炴��
+ *
+ * @author Michelle.Chung
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "mail")
+public class MailProperties {
+
+    /**
+     * 杩囨护寮�鍏�
+     */
+    private Boolean enabled;
+
+    /**
+     * SMTP鏈嶅姟鍣ㄥ煙鍚�
+     */
+    private String host;
+
+    /**
+     * SMTP鏈嶅姟绔彛
+     */
+    private Integer port;
+
+    /**
+     * 鏄惁闇�瑕佺敤鎴峰悕瀵嗙爜楠岃瘉
+     */
+    private Boolean auth;
+
+    /**
+     * 鐢ㄦ埛鍚�
+     */
+    private String user;
+
+    /**
+     * 瀵嗙爜
+     */
+    private String pass;
+
+    /**
+     * 鍙戦�佹柟锛岄伒寰猂FC-822鏍囧噯
+     */
+    private String from;
+
+    /**
+     * 浣跨敤 STARTTLS瀹夊叏杩炴帴锛孲TARTTLS鏄绾枃鏈�氫俊鍗忚鐨勬墿灞曘�傚畠灏嗙函鏂囨湰杩炴帴鍗囩骇涓哄姞瀵嗚繛鎺ワ紙TLS鎴朣SL锛夛紝 鑰屼笉鏄娇鐢ㄤ竴涓崟鐙殑鍔犲瘑閫氫俊绔彛銆�
+     */
+    private Boolean starttlsEnable;
+
+    /**
+     * 浣跨敤 SSL瀹夊叏杩炴帴
+     */
+    private Boolean sslEnable;
+
+    /**
+     * SMTP瓒呮椂鏃堕暱锛屽崟浣嶆绉掞紝缂虹渷鍊间笉瓒呮椂
+     */
+    private Long timeout;
+
+    /**
+     * Socket杩炴帴瓒呮椂鍊硷紝鍗曚綅姣锛岀己鐪佸�间笉瓒呮椂
+     */
+    private Long connectionTimeout;
+}
diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/MailUtils.java b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/MailUtils.java
new file mode 100644
index 0000000..81f2834
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/MailUtils.java
@@ -0,0 +1,468 @@
+package com.ruoyi.common.mail.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.CharUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.mail.*;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import jakarta.mail.Authenticator;
+import jakarta.mail.Session;
+import java.io.File;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * 閭欢宸ュ叿绫�
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class MailUtils {
+
+    private static final MailAccount ACCOUNT = SpringUtils.getBean(MailAccount.class);
+
+    /**
+     * 鑾峰彇閭欢鍙戦�佸疄渚�
+     */
+    public static MailAccount getMailAccount() {
+        return ACCOUNT;
+    }
+
+    /**
+     * 鑾峰彇閭欢鍙戦�佸疄渚� (鑷畾涔夊彂閫佷汉浠ュ強鎺堟潈鐮�)
+     *
+     * @param user 鍙戦�佷汉
+     * @param pass 鎺堟潈鐮�
+     */
+    public static MailAccount getMailAccount(String from, String user, String pass) {
+        ACCOUNT.setFrom(StringUtils.blankToDefault(from, ACCOUNT.getFrom()));
+        ACCOUNT.setUser(StringUtils.blankToDefault(user, ACCOUNT.getUser()));
+        ACCOUNT.setPass(StringUtils.blankToDefault(pass, ACCOUNT.getPass()));
+        return ACCOUNT;
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�佹枃鏈偖浠讹紝鍙戦�佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendText(String to, String subject, String content, File... files) {
+        return send(to, subject, content, false, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(String to, String subject, String content, File... files) {
+        return send(to, subject, content, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(String to, String subject, String content, boolean isHtml, File... files) {
+        return send(splitAddress(to), subject, content, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜恒�佹妱閫佷汉銆佸瘑閫佷汉鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to      鏀朵欢浜猴紝鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param cc      鎶勯�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param bcc     瀵嗛�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
+        return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�佹枃鏈偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String sendText(Collection<String> tos, String subject, String content, File... files) {
+        return send(tos, subject, content, false, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(Collection<String> tos, String subject, String content, File... files) {
+        return send(tos, subject, content, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
+        return send(tos, null, null, subject, content, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos     鏀朵欢浜哄垪琛�
+     * @param ccs     鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs    瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject 鏍囬
+     * @param content 姝f枃
+     * @param isHtml  鏄惁涓篐TML
+     * @param files   闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
+        return send(getMailAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
+    }
+
+    // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢璁よ瘉瀵硅薄
+     * @param to          鏀朵欢浜猴紝澶氫釜鏀朵欢浜洪�楀彿鎴栬�呭垎鍙烽殧寮�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
+        return send(mailAccount, splitAddress(to), subject, content, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
+        return send(mailAccount, tos, null, null, subject, content, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param ccs         鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs        瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
+        return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to       鏀朵欢浜�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
+        return send(to, subject, content, imageMap, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to       鏀朵欢浜�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(splitAddress(to), subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
+     * 澶氫釜鏀朵欢浜恒�佹妱閫佷汉銆佸瘑閫佷汉鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     *
+     * @param to       鏀朵欢浜猴紝鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param cc       鎶勯�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param bcc      瀵嗛�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰澶氫汉
+     *
+     * @param tos      鏀朵欢浜哄垪琛�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
+        return send(tos, subject, content, imageMap, true, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos      鏀朵欢浜哄垪琛�
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     */
+    public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(tos, null, null, subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
+     *
+     * @param tos      鏀朵欢浜哄垪琛�
+     * @param ccs      鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs     瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject  鏍囬
+     * @param content  姝f枃
+     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml   鏄惁涓篐TML
+     * @param files    闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.0.3
+     */
+    public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(getMailAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
+    }
+
+    // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢璁よ瘉瀵硅薄
+     * @param to          鏀朵欢浜猴紝澶氫釜鏀朵欢浜洪�楀彿鎴栬�呭垎鍙烽殧寮�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 3.2.0
+     */
+    public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.6.3
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount 閭欢甯愭埛淇℃伅
+     * @param tos         鏀朵欢浜哄垪琛�
+     * @param ccs         鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs        瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject     鏍囬
+     * @param content     姝f枃
+     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
+     * @param isHtml      鏄惁涓篐TML鏍煎紡
+     * @param files       闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.6.3
+     */
+    public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
+                              boolean isHtml, File... files) {
+        return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
+    }
+
+    /**
+     * 鏍规嵁閰嶇疆鏂囦欢锛岃幏鍙栭偖浠跺鎴风浼氳瘽
+     *
+     * @param mailAccount 閭欢璐︽埛閰嶇疆
+     * @param isSingleton 鏄惁鍗曚緥锛堝叏灞�鍏变韩浼氳瘽锛�
+     * @return {@link Session}
+     * @since 5.5.7
+     */
+    public static Session getSession(MailAccount mailAccount, boolean isSingleton) {
+        Authenticator authenticator = null;
+        if (mailAccount.isAuth()) {
+            authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
+        }
+
+        return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) //
+            : Session.getInstance(mailAccount.getSmtpProps(), authenticator);
+    }
+
+    // ------------------------------------------------------------------------------------------------------------------------ Private method start
+
+    /**
+     * 鍙戦�侀偖浠剁粰澶氫汉
+     *
+     * @param mailAccount      閭欢甯愭埛淇℃伅
+     * @param useGlobalSession 鏄惁鍏ㄥ眬鍏变韩Session
+     * @param tos              鏀朵欢浜哄垪琛�
+     * @param ccs              鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param bccs             瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
+     * @param subject          鏍囬
+     * @param content          姝f枃
+     * @param imageMap         鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:${cid}
+     * @param isHtml           鏄惁涓篐TML鏍煎紡
+     * @param files            闄勪欢鍒楄〃
+     * @return message-id
+     * @since 4.6.3
+     */
+    private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
+                               Map<String, InputStream> imageMap, boolean isHtml, File... files) {
+        final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession);
+
+        // 鍙�夋妱閫佷汉
+        if (CollUtil.isNotEmpty(ccs)) {
+            mail.setCcs(ccs.toArray(new String[0]));
+        }
+        // 鍙�夊瘑閫佷汉
+        if (CollUtil.isNotEmpty(bccs)) {
+            mail.setBccs(bccs.toArray(new String[0]));
+        }
+
+        mail.setTos(tos.toArray(new String[0]));
+        mail.setTitle(subject);
+        mail.setContent(content);
+        mail.setHtml(isHtml);
+        mail.setFiles(files);
+
+        // 鍥剧墖
+        if (MapUtil.isNotEmpty(imageMap)) {
+            for (Map.Entry<String, InputStream> entry : imageMap.entrySet()) {
+                mail.addImage(entry.getKey(), entry.getValue());
+                // 鍏抽棴娴�
+                IoUtil.close(entry.getValue());
+            }
+        }
+
+        return mail.send();
+    }
+
+    /**
+     * 灏嗗涓仈绯讳汉杞负鍒楄〃锛屽垎闅旂涓洪�楀彿鎴栬�呭垎鍙�
+     *
+     * @param addresses 澶氫釜鑱旂郴浜猴紝濡傛灉涓虹┖杩斿洖null
+     * @return 鑱旂郴浜哄垪琛�
+     */
+    private static List<String> splitAddress(String addresses) {
+        if (StrUtil.isBlank(addresses)) {
+            return null;
+        }
+
+        List<String> result;
+        if (StrUtil.contains(addresses, CharUtil.COMMA)) {
+            result = StrUtil.splitTrim(addresses, CharUtil.COMMA);
+        } else if (StrUtil.contains(addresses, ';')) {
+            result = StrUtil.splitTrim(addresses, ';');
+        } else {
+            result = CollUtil.newArrayList(addresses);
+        }
+        return result;
+    }
+    // ------------------------------------------------------------------------------------------------------------------------ Private method end
+
+}
diff --git a/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/UserPassAuthenticator.java b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/UserPassAuthenticator.java
new file mode 100644
index 0000000..8d4d6f3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mail/src/main/java/com/ruoyi/common/mail/utils/UserPassAuthenticator.java
@@ -0,0 +1,33 @@
+package com.ruoyi.common.mail.utils;
+
+import jakarta.mail.Authenticator;
+import jakarta.mail.PasswordAuthentication;
+
+/**
+ * 鐢ㄦ埛鍚嶅瘑鐮侀獙璇佸櫒
+ *
+ * @author looly
+ * @since 3.1.2
+ */
+public class UserPassAuthenticator extends Authenticator {
+
+	private final String user;
+	private final String pass;
+
+	/**
+	 * 鏋勯��
+	 *
+	 * @param user 鐢ㄦ埛鍚�
+	 * @param pass 瀵嗙爜
+	 */
+	public UserPassAuthenticator(String user, String pass) {
+		this.user = user;
+		this.pass = pass;
+	}
+
+	@Override
+	protected PasswordAuthentication getPasswordAuthentication() {
+		return new PasswordAuthentication(this.user, this.pass);
+	}
+
+}
diff --git a/ruoyi-common/ruoyi-common-mail/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-mail/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..f067b8b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mail/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.mail.config.MailConfig
diff --git a/ruoyi-common/ruoyi-common-mybatis/pom.xml b/ruoyi-common/ruoyi-common-mybatis/pom.xml
new file mode 100644
index 0000000..67e381f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/pom.xml
@@ -0,0 +1,48 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-mybatis</artifactId>
+
+    <description>
+        ruoyi-common-mybatis 鏁版嵁搴撴湇鍔�
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-satoken</artifactId>
+        </dependency>
+
+        <!-- dynamic-datasource 澶氭暟鎹簮-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+
+        <!-- sql鎬ц兘鍒嗘瀽鎻掍欢 -->
+        <dependency>
+            <groupId>p6spy</groupId>
+            <artifactId>p6spy</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaHeaderProcessor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaHeaderProcessor.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaHeaderProcessor.java
rename to ruoyi-common/ruoyi-common-mybatis/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaHeaderProcessor.java
diff --git a/ruoyi-common/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaSessionProcessor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaSessionProcessor.java
similarity index 100%
rename from ruoyi-common/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaSessionProcessor.java
rename to ruoyi-common/ruoyi-common-mybatis/src/main/java/com/baomidou/dynamic/datasource/processor/jakarta/DsJakartaSessionProcessor.java
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataColumn.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataColumn.java
new file mode 100644
index 0000000..bf703a2
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataColumn.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.mybatis.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 鏁版嵁鏉冮檺
+ *
+ * 涓�涓敞瑙e彧鑳藉搴斾竴涓ā鏉�
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataColumn {
+
+    /**
+     * 鍗犱綅绗﹀叧閿瓧
+     */
+    String[] key() default "deptName";
+
+    /**
+     * 鍗犱綅绗︽浛鎹㈠��
+     */
+    String[] value() default "dept_id";
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataPermission.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataPermission.java
new file mode 100644
index 0000000..288c195
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/annotation/DataPermission.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.mybatis.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 鏁版嵁鏉冮檺缁�
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataPermission {
+
+    DataColumn[] value();
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/config/MybatisPlusConfig.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..ea76cb3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/config/MybatisPlusConfig.java
@@ -0,0 +1,102 @@
+package com.ruoyi.common.mybatis.config;
+
+import cn.hutool.core.net.NetUtil;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
+import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.ruoyi.common.mybatis.handler.CreateAndUpdateMetaObjectHandler;
+import com.ruoyi.common.mybatis.interceptor.PlusDataPermissionInterceptor;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * mybatis-plus閰嶇疆绫�(涓嬫柟娉ㄩ噴鏈夋彃浠朵粙缁�)
+ *
+ * @author Lion Li
+ */
+@EnableTransactionManagement(proxyTargetClass = true)
+@AutoConfiguration
+@MapperScan("${mybatis-plus.mapperPackage}")
+public class MybatisPlusConfig {
+
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        // 鏁版嵁鏉冮檺澶勭悊
+        interceptor.addInnerInterceptor(dataPermissionInterceptor());
+        // 鍒嗛〉鎻掍欢
+        interceptor.addInnerInterceptor(paginationInnerInterceptor());
+        // 涔愯閿佹彃浠�
+        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
+        return interceptor;
+    }
+
+    /**
+     * 鏁版嵁鏉冮檺鎷︽埅鍣�
+     */
+    public PlusDataPermissionInterceptor dataPermissionInterceptor() {
+        return new PlusDataPermissionInterceptor();
+    }
+
+    /**
+     * 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷
+     */
+    public PaginationInnerInterceptor paginationInnerInterceptor() {
+        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
+        // 璁剧疆鏈�澶у崟椤甸檺鍒舵暟閲忥紝榛樿 500 鏉★紝-1 涓嶅彈闄愬埗
+        paginationInnerInterceptor.setMaxLimit(-1L);
+        // 鍒嗛〉鍚堢悊鍖�
+        paginationInnerInterceptor.setOverflow(true);
+        return paginationInnerInterceptor;
+    }
+
+    /**
+     * 涔愯閿佹彃浠�
+     */
+    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
+        return new OptimisticLockerInnerInterceptor();
+    }
+
+    /**
+     * 鍏冨璞″瓧娈靛~鍏呮帶鍒跺櫒
+     */
+    @Bean
+    public MetaObjectHandler metaObjectHandler() {
+        return new CreateAndUpdateMetaObjectHandler();
+    }
+
+    /**
+     * 浣跨敤缃戝崱淇℃伅缁戝畾闆姳鐢熸垚鍣�
+     * 闃叉闆嗙兢闆姳ID閲嶅
+     */
+    @Bean
+    public IdentifierGenerator idGenerator() {
+        return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
+    }
+
+    /**
+     * PaginationInnerInterceptor 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷
+     * https://baomidou.com/pages/97710a/
+     * OptimisticLockerInnerInterceptor 涔愯閿佹彃浠�
+     * https://baomidou.com/pages/0d93c0/
+     * MetaObjectHandler 鍏冨璞″瓧娈靛~鍏呮帶鍒跺櫒
+     * https://baomidou.com/pages/4c6bcf/
+     * ISqlInjector sql娉ㄥ叆鍣�
+     * https://baomidou.com/pages/42ea4a/
+     * BlockAttackInnerInterceptor 濡傛灉鏄鍏ㄨ〃鐨勫垹闄ゆ垨鏇存柊鎿嶄綔锛屽氨浼氱粓姝㈣鎿嶄綔
+     * https://baomidou.com/pages/f9a237/
+     * IllegalSQLInnerInterceptor sql鎬ц兘瑙勮寖鎻掍欢(鍨冨溇SQL鎷︽埅)
+     * IdentifierGenerator 鑷畾涔変富閿瓥鐣�
+     * https://baomidou.com/pages/568eb2/
+     * TenantLineInnerInterceptor 澶氱鎴锋彃浠�
+     * https://baomidou.com/pages/aef2f2/
+     * DynamicTableNameInnerInterceptor 鍔ㄦ�佽〃鍚嶆彃浠�
+     * https://baomidou.com/pages/2a45ff/
+     */
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/mapper/BaseMapperPlus.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/mapper/BaseMapperPlus.java
new file mode 100644
index 0000000..2c40e17
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/mapper/BaseMapperPlus.java
@@ -0,0 +1,192 @@
+package com.ruoyi.common.mybatis.core.mapper;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+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.*;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.toolkit.Db;
+import com.ruoyi.common.core.utils.BeanCopyUtils;
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鑷畾涔� Mapper 鎺ュ彛, 瀹炵幇 鑷畾涔夋墿灞�
+ *
+ * @param <M> mapper 娉涘瀷
+ * @param <T> table 娉涘瀷
+ * @param <V> vo 娉涘瀷
+ * @author Lion Li
+ * @since 2021-05-13
+ */
+@SuppressWarnings("unchecked")
+public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
+
+    Log log = LogFactory.getLog(BaseMapperPlus.class);
+
+    default Class<V> currentVoClass() {
+        return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2);
+    }
+
+    default Class<T> currentModelClass() {
+        return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 1);
+    }
+
+    default Class<M> currentMapperClass() {
+        return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 0);
+    }
+
+    default List<T> selectList() {
+        return this.selectList(new QueryWrapper<>());
+    }
+
+    /**
+     * 鎵归噺鎻掑叆
+     */
+    default boolean insertBatch(Collection<T> entityList) {
+        return Db.saveBatch(entityList);
+    }
+
+    /**
+     * 鎵归噺鏇存柊
+     */
+    default boolean updateBatchById(Collection<T> entityList) {
+        return Db.updateBatchById(entityList);
+    }
+
+    /**
+     * 鎵归噺鎻掑叆鎴栨洿鏂�
+     */
+    default boolean insertOrUpdateBatch(Collection<T> entityList) {
+        return Db.saveOrUpdateBatch(entityList);
+    }
+
+    /**
+     * 鎵归噺鎻掑叆(鍖呭惈闄愬埗鏉℃暟)
+     */
+    default boolean insertBatch(Collection<T> entityList, int batchSize) {
+        return Db.saveBatch(entityList, batchSize);
+    }
+
+    /**
+     * 鎵归噺鏇存柊(鍖呭惈闄愬埗鏉℃暟)
+     */
+    default boolean updateBatchById(Collection<T> entityList, int batchSize) {
+        return Db.updateBatchById(entityList, batchSize);
+    }
+
+    /**
+     * 鎵归噺鎻掑叆鎴栨洿鏂�(鍖呭惈闄愬埗鏉℃暟)
+     */
+    default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
+        return Db.saveOrUpdateBatch(entityList, batchSize);
+    }
+
+    /**
+     * 鎻掑叆鎴栨洿鏂�(鍖呭惈闄愬埗鏉℃暟)
+     */
+    default boolean insertOrUpdate(T entity) {
+        return Db.saveOrUpdate(entity);
+    }
+
+    default V selectVoById(Serializable id) {
+        return selectVoById(id, this.currentVoClass());
+    }
+
+    /**
+     * 鏍规嵁 ID 鏌ヨ
+     */
+    default <C> C selectVoById(Serializable id, Class<C> voClass) {
+        T obj = this.selectById(id);
+        if (ObjectUtil.isNull(obj)) {
+            return null;
+        }
+        return BeanCopyUtils.copy(obj, voClass);
+    }
+
+    default List<V> selectVoBatchIds(Collection<? extends Serializable> idList) {
+        return selectVoBatchIds(idList, this.currentVoClass());
+    }
+
+    /**
+     * 鏌ヨ锛堟牴鎹甀D 鎵归噺鏌ヨ锛�
+     */
+    default <C> List<C> selectVoBatchIds(Collection<? extends Serializable> idList, Class<C> voClass) {
+        List<T> list = this.selectBatchIds(idList);
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+        return BeanCopyUtils.copyList(list, voClass);
+    }
+
+    default List<V> selectVoByMap(Map<String, Object> map) {
+        return selectVoByMap(map, this.currentVoClass());
+    }
+
+    /**
+     * 鏌ヨ锛堟牴鎹� columnMap 鏉′欢锛�
+     */
+    default <C> List<C> selectVoByMap(Map<String, Object> map, Class<C> voClass) {
+        List<T> list = this.selectByMap(map);
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+        return BeanCopyUtils.copyList(list, voClass);
+    }
+
+    default V selectVoOne(Wrapper<T> wrapper) {
+        return selectVoOne(wrapper, this.currentVoClass());
+    }
+
+    /**
+     * 鏍规嵁 entity 鏉′欢锛屾煡璇竴鏉¤褰�
+     */
+    default <C> C selectVoOne(Wrapper<T> wrapper, Class<C> voClass) {
+        T obj = this.selectOne(wrapper);
+        if (ObjectUtil.isNull(obj)) {
+            return null;
+        }
+        return BeanCopyUtils.copy(obj, voClass);
+    }
+
+    default List<V> selectVoList(Wrapper<T> wrapper) {
+        return selectVoList(wrapper, this.currentVoClass());
+    }
+
+    /**
+     * 鏍规嵁 entity 鏉′欢锛屾煡璇㈠叏閮ㄨ褰�
+     */
+    default <C> List<C> selectVoList(Wrapper<T> wrapper, Class<C> voClass) {
+        List<T> list = this.selectList(wrapper);
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+        return BeanCopyUtils.copyList(list, voClass);
+    }
+
+    default <P extends IPage<V>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper) {
+        return selectVoPage(page, wrapper, this.currentVoClass());
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨVO
+     */
+    default <C, P extends IPage<C>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper, Class<C> voClass) {
+        IPage<T> pageData = this.selectPage(page, wrapper);
+        IPage<C> voPage = new Page<>(pageData.getCurrent(), pageData.getSize(), pageData.getTotal());
+        if (CollUtil.isEmpty(pageData.getRecords())) {
+            return (P) voPage;
+        }
+        voPage.setRecords(BeanCopyUtils.copyList(pageData.getRecords(), voClass));
+        return (P) voPage;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/PageQuery.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/PageQuery.java
new file mode 100644
index 0000000..30a3e2d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/PageQuery.java
@@ -0,0 +1,114 @@
+package com.ruoyi.common.mybatis.core.page;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.sql.SqlUtil;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鍒嗛〉鏌ヨ瀹炰綋绫�
+ *
+ * @author Lion Li
+ */
+
+@Data
+public class PageQuery implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鍒嗛〉澶у皬
+     */
+    private Integer pageSize;
+
+    /**
+     * 褰撳墠椤垫暟
+     */
+    private Integer pageNum;
+
+    /**
+     * 鎺掑簭鍒�
+     */
+    private String orderByColumn;
+
+    /**
+     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
+     */
+    private String isAsc;
+
+    /**
+     * 褰撳墠璁板綍璧峰绱㈠紩 榛樿鍊�
+     */
+    public static final int DEFAULT_PAGE_NUM = 1;
+
+    /**
+     * 姣忛〉鏄剧ず璁板綍鏁� 榛樿鍊� 榛樿鏌ュ叏閮�
+     */
+    public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
+
+    public <T> Page<T> build() {
+        Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
+        Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
+        if (pageNum <= 0) {
+            pageNum = DEFAULT_PAGE_NUM;
+        }
+        Page<T> page = new Page<>(pageNum, pageSize);
+        List<OrderItem> orderItems = buildOrderItem();
+        if (CollUtil.isNotEmpty(orderItems)) {
+            page.addOrder(orderItems);
+        }
+        return page;
+    }
+
+    /**
+     * 鏋勫缓鎺掑簭
+     *
+     * 鏀寔鐨勭敤娉曞涓�:
+     * {isAsc:"asc",orderByColumn:"id"} order by id asc
+     * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc
+     * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc
+     * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc
+     */
+    private List<OrderItem> buildOrderItem() {
+        if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) {
+            return null;
+        }
+        String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
+        orderBy = StringUtils.toUnderScoreCase(orderBy);
+
+        // 鍏煎鍓嶇鎺掑簭绫诲瀷
+        isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"});
+
+        String[] orderByArr = orderBy.split(",");
+        String[] isAscArr = isAsc.split(",");
+        if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) {
+            throw new ServiceException("鎺掑簭鍙傛暟鏈夎");
+        }
+
+        List<OrderItem> list = new ArrayList<>();
+        // 姣忎釜瀛楁鍚勮嚜鎺掑簭
+        for (int i = 0; i < orderByArr.length; i++) {
+            String orderByStr = orderByArr[i];
+            String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i];
+            if ("asc".equals(isAscStr)) {
+                list.add(OrderItem.asc(orderByStr));
+            } else if ("desc".equals(isAscStr)) {
+                list.add(OrderItem.desc(orderByStr));
+            } else {
+                throw new ServiceException("鎺掑簭鍙傛暟鏈夎");
+            }
+        }
+        return list;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/TableDataInfo.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/TableDataInfo.java
new file mode 100644
index 0000000..feaf03f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/core/page/TableDataInfo.java
@@ -0,0 +1,81 @@
+package com.ruoyi.common.mybatis.core.page;
+
+import cn.hutool.http.HttpStatus;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 琛ㄦ牸鍒嗛〉鏁版嵁瀵硅薄
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+public class TableDataInfo<T> implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鎬昏褰曟暟
+     */
+    private long total;
+
+    /**
+     * 鍒楄〃鏁版嵁
+     */
+    private List<T> rows;
+
+    /**
+     * 娑堟伅鐘舵�佺爜
+     */
+    private int code;
+
+    /**
+     * 娑堟伅鍐呭
+     */
+    private String msg;
+
+    /**
+     * 鍒嗛〉
+     *
+     * @param list  鍒楄〃鏁版嵁
+     * @param total 鎬昏褰曟暟
+     */
+    public TableDataInfo(List<T> list, long total) {
+        this.rows = list;
+        this.total = total;
+    }
+
+    public static <T> TableDataInfo<T> build(IPage<T> page) {
+        TableDataInfo<T> rspData = new TableDataInfo<>();
+        rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setMsg("鏌ヨ鎴愬姛");
+        rspData.setRows(page.getRecords());
+        rspData.setTotal(page.getTotal());
+        return rspData;
+    }
+
+    public static <T> TableDataInfo<T> build(List<T> list) {
+        TableDataInfo<T> rspData = new TableDataInfo<>();
+        rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setMsg("鏌ヨ鎴愬姛");
+        rspData.setRows(list);
+        rspData.setTotal(list.size());
+        return rspData;
+    }
+
+    public static <T> TableDataInfo<T> build() {
+        TableDataInfo<T> rspData = new TableDataInfo<>();
+        rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setMsg("鏌ヨ鎴愬姛");
+        return rspData;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataBaseType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataBaseType.java
new file mode 100644
index 0000000..b50667e
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataBaseType.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.mybatis.enums;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 鏁版嵁搴撶被鍨�
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum DataBaseType {
+
+    /**
+     * MySQL
+     */
+    MY_SQL("MySQL"),
+
+    /**
+     * Oracle
+     */
+    ORACLE("Oracle"),
+
+    /**
+     * PostgreSQL
+     */
+    POSTGRE_SQL("PostgreSQL"),
+
+    /**
+     * SQL Server
+     */
+    SQL_SERVER("Microsoft SQL Server");
+
+    private final String type;
+
+    public static DataBaseType find(String databaseProductName) {
+        if (StringUtils.isBlank(databaseProductName)) {
+            return null;
+        }
+        for (DataBaseType type : values()) {
+            if (type.getType().equals(databaseProductName)) {
+                return type;
+            }
+        }
+        return null;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataScopeType.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataScopeType.java
new file mode 100644
index 0000000..0abb3b2
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/enums/DataScopeType.java
@@ -0,0 +1,72 @@
+package com.ruoyi.common.mybatis.enums;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 鏁版嵁鏉冮檺绫诲瀷
+ * <p>
+ * 璇硶鏀寔 spel 妯℃澘琛ㄨ揪寮�
+ * <p>
+ * 鍐呯疆鏁版嵁 user 褰撳墠鐢ㄦ埛 鍐呭鍙傝�� LoginUser
+ * 濡傞渶鎵╁睍鏁版嵁 鍙娇鐢� {@link com.ruoyi.common.mybatis.helper.DataPermissionHelper} 鎿嶄綔
+ * 鍐呯疆鏈嶅姟 sdss 绯荤粺鏁版嵁鏉冮檺鏈嶅姟 鍐呭鍙傝�� SysDataScopeService
+ * 濡傞渶鎵╁睍鏇村鑷畾涔夋湇鍔� 鍙互鍙傝�� sdss 鑷缂栧啓
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+@Getter
+@AllArgsConstructor
+public enum DataScopeType {
+
+    /**
+     * 鍏ㄩ儴鏁版嵁鏉冮檺
+     */
+    ALL("1", "", ""),
+
+    /**
+     * 鑷畾鏁版嵁鏉冮檺
+     */
+    CUSTOM("2", " #{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} ) ", ""),
+
+    /**
+     * 閮ㄩ棬鏁版嵁鏉冮檺
+     */
+    DEPT("3", " #{#deptName} = #{#user.deptId} ", ""),
+
+    /**
+     * 閮ㄩ棬鍙婁互涓嬫暟鎹潈闄�
+     */
+    DEPT_AND_CHILD("4", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} )", ""),
+
+    /**
+     * 浠呮湰浜烘暟鎹潈闄�
+     */
+    SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 ");
+
+    private final String code;
+
+    /**
+     * 璇硶 閲囩敤 spel 妯℃澘琛ㄨ揪寮�
+     */
+    private final String sqlTemplate;
+
+    /**
+     * 涓嶆弧瓒� sqlTemplate 鍒欏~鍏�
+     */
+    private final String elseSql;
+
+    public static DataScopeType findCode(String code) {
+        if (StringUtils.isBlank(code)) {
+            return null;
+        }
+        for (DataScopeType type : values()) {
+            if (type.getCode().equals(code)) {
+                return type;
+            }
+        }
+        return null;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java
new file mode 100644
index 0000000..4ab329d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/CreateAndUpdateMetaObjectHandler.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.mybatis.handler;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpStatus;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.reflection.MetaObject;
+
+import java.util.Date;
+
+/**
+ * MP娉ㄥ叆澶勭悊鍣�
+ *
+ * @author Lion Li
+ * @date 2021/4/25
+ */
+@Slf4j
+public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
+
+    @Override
+    public void insertFill(MetaObject metaObject) {
+        try {
+            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
+                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
+                Date current = ObjectUtil.isNotNull(baseEntity.getCreateTime())
+                    ? baseEntity.getCreateTime() : new Date();
+                baseEntity.setCreateTime(current);
+                baseEntity.setUpdateTime(current);
+                String username = StringUtils.isNotBlank(baseEntity.getCreateBy())
+                    ? baseEntity.getCreateBy() : getLoginUsername();
+                // 褰撳墠宸茬櫥褰� 涓� 鍒涘缓浜轰负绌� 鍒欏~鍏�
+                baseEntity.setCreateBy(username);
+                // 褰撳墠宸茬櫥褰� 涓� 鏇存柊浜轰负绌� 鍒欏~鍏�
+                baseEntity.setUpdateBy(username);
+            }
+        } catch (Exception e) {
+            throw new ServiceException("鑷姩娉ㄥ叆寮傚父 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
+        }
+    }
+
+    @Override
+    public void updateFill(MetaObject metaObject) {
+        try {
+            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
+                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
+                Date current = new Date();
+                // 鏇存柊鏃堕棿濉厖(涓嶇涓轰笉涓虹┖)
+                baseEntity.setUpdateTime(current);
+                String username = getLoginUsername();
+                // 褰撳墠宸茬櫥褰� 鏇存柊浜哄~鍏�(涓嶇涓轰笉涓虹┖)
+                if (StringUtils.isNotBlank(username)) {
+                    baseEntity.setUpdateBy(username);
+                }
+            }
+        } catch (Exception e) {
+            throw new ServiceException("鑷姩娉ㄥ叆寮傚父 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 鑾峰彇鐧诲綍鐢ㄦ埛鍚�
+     */
+    private String getLoginUsername() {
+        LoginUser loginUser;
+        try {
+            loginUser = LoginHelper.getLoginUser();
+        } catch (Exception e) {
+            log.warn("鑷姩娉ㄥ叆璀﹀憡 => 鐢ㄦ埛鏈櫥褰�");
+            return null;
+        }
+        return loginUser.getUsername();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java
new file mode 100644
index 0000000..9553525
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/handler/PlusDataPermissionHandler.java
@@ -0,0 +1,199 @@
+package com.ruoyi.common.mybatis.handler;
+
+import cn.hutool.core.annotation.AnnotationUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ConcurrentHashSet;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ClassUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.core.domain.dto.RoleDTO;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.mybatis.annotation.DataColumn;
+import com.ruoyi.common.mybatis.annotation.DataPermission;
+import com.ruoyi.common.mybatis.enums.DataScopeType;
+import com.ruoyi.common.mybatis.helper.DataPermissionHelper;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import lombok.extern.slf4j.Slf4j;
+import net.sf.jsqlparser.JSQLParserException;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.Parenthesis;
+import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
+import net.sf.jsqlparser.parser.CCJSqlParserUtil;
+import org.springframework.context.expression.BeanFactoryResolver;
+import org.springframework.expression.BeanResolver;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.ParserContext;
+import org.springframework.expression.common.TemplateParserContext;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 鏁版嵁鏉冮檺杩囨护
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+@Slf4j
+public class PlusDataPermissionHandler {
+
+    /**
+     * 鏂规硶鎴栫被(鍚嶇О) 涓� 娉ㄨВ鐨勬槧灏勫叧绯荤紦瀛�
+     */
+    private final Map<String, DataPermission> dataPermissionCacheMap = new ConcurrentHashMap<>();
+
+    /**
+     * 鏃犳晥娉ㄨВ鏂规硶缂撳瓨鐢ㄤ簬蹇�熻繑鍥�
+     */
+    private final Set<String> invalidCacheSet = new ConcurrentHashSet<>();
+
+    /**
+     * spel 瑙f瀽鍣�
+     */
+    private final ExpressionParser parser = new SpelExpressionParser();
+    private final ParserContext parserContext = new TemplateParserContext();
+    /**
+     * bean瑙f瀽鍣� 鐢ㄤ簬澶勭悊 spel 琛ㄨ揪寮忎腑瀵� bean 鐨勮皟鐢�
+     */
+    private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory());
+
+
+    public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) {
+        DataColumn[] dataColumns = findAnnotation(mappedStatementId);
+        if (ArrayUtil.isEmpty(dataColumns)) {
+            invalidCacheSet.add(mappedStatementId);
+            return where;
+        }
+        LoginUser currentUser = DataPermissionHelper.getVariable("user");
+        if (ObjectUtil.isNull(currentUser)) {
+            currentUser = LoginHelper.getLoginUser();
+            DataPermissionHelper.setVariable("user", currentUser);
+        }
+        // 濡傛灉鏄秴绾х鐞嗗憳锛屽垯涓嶈繃婊ゆ暟鎹�
+        if (LoginHelper.isAdmin()) {
+            return where;
+        }
+        String dataFilterSql = buildDataFilter(dataColumns, isSelect);
+        if (StringUtils.isBlank(dataFilterSql)) {
+            return where;
+        }
+        try {
+            Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql);
+            // 鏁版嵁鏉冮檺浣跨敤鍗曠嫭鐨勬嫭鍙� 闃叉涓庡叾浠栨潯浠跺啿绐�
+            Parenthesis parenthesis = new Parenthesis(expression);
+            if (ObjectUtil.isNotNull(where)) {
+                return new AndExpression(where, parenthesis);
+            } else {
+                return parenthesis;
+            }
+        } catch (JSQLParserException e) {
+            throw new ServiceException("鏁版嵁鏉冮檺瑙f瀽寮傚父 => " + e.getMessage());
+        }
+    }
+
+    /**
+     * 鏋勯�犳暟鎹繃婊ql
+     */
+    private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) {
+        // 鏇存柊鎴栧垹闄ら渶婊¤冻鎵�鏈夋潯浠�
+        String joinStr = isSelect ? " OR " : " AND ";
+        LoginUser user = DataPermissionHelper.getVariable("user");
+        StandardEvaluationContext context = new StandardEvaluationContext();
+        context.setBeanResolver(beanResolver);
+        DataPermissionHelper.getContext().forEach(context::setVariable);
+        Set<String> conditions = new HashSet<>();
+        for (RoleDTO role : user.getRoles()) {
+            user.setRoleId(role.getRoleId());
+            // 鑾峰彇瑙掕壊鏉冮檺娉涘瀷
+            DataScopeType type = DataScopeType.findCode(role.getDataScope());
+            if (ObjectUtil.isNull(type)) {
+                throw new ServiceException("瑙掕壊鏁版嵁鑼冨洿寮傚父 => " + role.getDataScope());
+            }
+            // 鍏ㄩ儴鏁版嵁鏉冮檺鐩存帴杩斿洖
+            if (type == DataScopeType.ALL) {
+                return "";
+            }
+            boolean isSuccess = false;
+            for (DataColumn dataColumn : dataColumns) {
+                if (dataColumn.key().length != dataColumn.value().length) {
+                    throw new ServiceException("瑙掕壊鏁版嵁鑼冨洿寮傚父 => key涓巚alue闀垮害涓嶅尮閰�");
+                }
+                // 涓嶅寘鍚� key 鍙橀噺 鍒欎笉澶勭悊
+                if (!StringUtils.containsAny(type.getSqlTemplate(),
+                    Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new)
+                )) {
+                    continue;
+                }
+                // 璁剧疆娉ㄨВ鍙橀噺 key 涓鸿〃杈惧紡鍙橀噺 value 涓哄彉閲忓��
+                for (int i = 0; i < dataColumn.key().length; i++) {
+                    context.setVariable(dataColumn.key()[i], dataColumn.value()[i]);
+                }
+
+                // 瑙f瀽sql妯℃澘骞跺~鍏�
+                String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class);
+                conditions.add(joinStr + sql);
+                isSuccess = true;
+            }
+            // 鏈鐞嗘垚鍔熷垯濉厖鍏滃簳鏂规
+            if (!isSuccess && StringUtils.isNotBlank(type.getElseSql())) {
+                conditions.add(joinStr + type.getElseSql());
+            }
+        }
+
+        if (CollUtil.isNotEmpty(conditions)) {
+            String sql = StreamUtils.join(conditions, Function.identity(), "");
+            return sql.substring(joinStr.length());
+        }
+        return "";
+    }
+
+    private DataColumn[] findAnnotation(String mappedStatementId) {
+        StringBuilder sb = new StringBuilder(mappedStatementId);
+        int index = sb.lastIndexOf(".");
+        String clazzName = sb.substring(0, index);
+        String methodName = sb.substring(index + 1, sb.length());
+        Class<?> clazz = ClassUtil.loadClass(clazzName);
+        List<Method> methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz))
+            .filter(method -> method.getName().equals(methodName)).collect(Collectors.toList());
+        DataPermission dataPermission;
+        // 鑾峰彇鏂规硶娉ㄨВ
+        for (Method method : methods) {
+            dataPermission = dataPermissionCacheMap.get(mappedStatementId);
+            if (ObjectUtil.isNotNull(dataPermission)) {
+                return dataPermission.value();
+            }
+            if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) {
+                dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class);
+                dataPermissionCacheMap.put(mappedStatementId, dataPermission);
+                return dataPermission.value();
+            }
+        }
+        dataPermission = dataPermissionCacheMap.get(clazz.getName());
+        if (ObjectUtil.isNotNull(dataPermission)) {
+            return dataPermission.value();
+        }
+        // 鑾峰彇绫绘敞瑙�
+        if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) {
+            dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class);
+            dataPermissionCacheMap.put(clazz.getName(), dataPermission);
+            return dataPermission.value();
+        }
+        return null;
+    }
+
+    /**
+     * 鏄惁涓烘棤鏁堟柟娉� 鏃犳暟鎹潈闄�
+     */
+    public boolean isInvalid(String mappedStatementId) {
+        return invalidCacheSet.contains(mappedStatementId);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataBaseHelper.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataBaseHelper.java
new file mode 100644
index 0000000..c090179
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataBaseHelper.java
@@ -0,0 +1,72 @@
+package com.ruoyi.common.mybatis.helper;
+
+import cn.hutool.core.convert.Convert;
+import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.mybatis.enums.DataBaseType;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+/**
+ * 鏁版嵁搴撳姪鎵�
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DataBaseHelper {
+
+    private static final DynamicRoutingDataSource DS = SpringUtils.getBean(DynamicRoutingDataSource.class);
+
+    /**
+     * 鑾峰彇褰撳墠鏁版嵁搴撶被鍨�
+     */
+    public static DataBaseType getDataBaseType() {
+        DataSource dataSource = DS.determineDataSource();
+        try (Connection conn = dataSource.getConnection()) {
+            DatabaseMetaData metaData = conn.getMetaData();
+            String databaseProductName = metaData.getDatabaseProductName();
+            return DataBaseType.find(databaseProductName);
+        } catch (SQLException e) {
+            throw new ServiceException(e.getMessage());
+        }
+    }
+
+    public static boolean isMySql() {
+        return DataBaseType.MY_SQL == getDataBaseType();
+    }
+
+    public static boolean isOracle() {
+        return DataBaseType.ORACLE == getDataBaseType();
+    }
+
+    public static boolean isPostgerSql() {
+        return DataBaseType.POSTGRE_SQL == getDataBaseType();
+    }
+
+    public static boolean isSqlServer() {
+        return DataBaseType.SQL_SERVER == getDataBaseType();
+    }
+
+    public static String findInSet(Object var1, String var2) {
+        DataBaseType dataBasyType = getDataBaseType();
+        String var = Convert.toStr(var1);
+        if (dataBasyType == DataBaseType.SQL_SERVER) {
+            // charindex(',100,' , ',0,100,101,') <> 0
+            return "charindex('," + var + ",' , ','+" + var2 + "+',') <> 0";
+        } else if (dataBasyType == DataBaseType.POSTGRE_SQL) {
+            // (select position(',100,' in ',0,100,101,')) <> 0
+            return "(select position('," + var + ",' in ','||" + var2 + "||',')) <> 0";
+        } else if (dataBasyType == DataBaseType.ORACLE) {
+            // instr(',0,100,101,' , ',100,') <> 0
+            return "instr(','||" + var2 + "||',' , '," + var + ",') <> 0";
+        }
+        // find_in_set(100 , '0,100,101')
+        return "find_in_set(" + var + " , " + var2 + ") <> 0";
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataPermissionHelper.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataPermissionHelper.java
new file mode 100644
index 0000000..9555b01
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/DataPermissionHelper.java
@@ -0,0 +1,47 @@
+package com.ruoyi.common.mybatis.helper;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.context.model.SaStorage;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鏁版嵁鏉冮檺鍔╂墜
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@SuppressWarnings("unchecked cast")
+public class DataPermissionHelper {
+
+    private static final String DATA_PERMISSION_KEY = "data:permission";
+
+    public static <T> T getVariable(String key) {
+        Map<String, Object> context = getContext();
+        return (T) context.get(key);
+    }
+
+
+    public static void setVariable(String key, Object value) {
+        Map<String, Object> context = getContext();
+        context.put(key, value);
+    }
+
+    public static Map<String, Object> getContext() {
+        SaStorage saStorage = SaHolder.getStorage();
+        Object attribute = saStorage.get(DATA_PERMISSION_KEY);
+        if (ObjectUtil.isNull(attribute)) {
+            saStorage.set(DATA_PERMISSION_KEY, new HashMap<>());
+            attribute = saStorage.get(DATA_PERMISSION_KEY);
+        }
+        if (attribute instanceof Map) {
+            return (Map<String, Object>) attribute;
+        }
+        throw new NullPointerException("data permission context type exception");
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/MybatisExceptionHandler.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/MybatisExceptionHandler.java
new file mode 100644
index 0000000..532cd79
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/helper/MybatisExceptionHandler.java
@@ -0,0 +1,46 @@
+package com.ruoyi.common.mybatis.helper;
+
+import com.ruoyi.common.core.domain.R;
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.MyBatisSystemException;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * Mybatis寮傚父澶勭悊鍣�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@RestControllerAdvice
+public class MybatisExceptionHandler {
+
+    /**
+     * 涓婚敭鎴朥NIQUE绱㈠紩锛屾暟鎹噸澶嶅紓甯�
+     */
+    @ExceptionHandler(DuplicateKeyException.class)
+    public R<Void> handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鏁版嵁搴撲腑宸插瓨鍦ㄨ褰�'{}'", requestURI, e.getMessage());
+        return R.fail("鏁版嵁搴撲腑宸插瓨鍦ㄨ璁板綍锛岃鑱旂郴绠$悊鍛樼‘璁�");
+    }
+
+    /**
+     * Mybatis绯荤粺寮傚父 閫氱敤澶勭悊
+     */
+    @ExceptionHandler(MyBatisSystemException.class)
+    public R<Void> handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        String message = e.getMessage();
+        if (message.contains("CannotFindDataSourceException")) {
+            log.error("璇锋眰鍦板潃'{}', 鏈壘鍒版暟鎹簮", requestURI);
+            return R.fail("鏈壘鍒版暟鎹簮锛岃鑱旂郴绠$悊鍛樼‘璁�");
+        }
+        log.error("璇锋眰鍦板潃'{}', Mybatis绯荤粺寮傚父", requestURI, e);
+        return R.fail(message);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/interceptor/PlusDataPermissionInterceptor.java b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/interceptor/PlusDataPermissionInterceptor.java
new file mode 100644
index 0000000..9b6a0b0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/java/com/ruoyi/common/mybatis/interceptor/PlusDataPermissionInterceptor.java
@@ -0,0 +1,108 @@
+package com.ruoyi.common.mybatis.interceptor;
+
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
+import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
+import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
+import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
+import com.ruoyi.common.mybatis.handler.PlusDataPermissionHandler;
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.statement.delete.Delete;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.select.SelectBody;
+import net.sf.jsqlparser.statement.select.SetOperationList;
+import net.sf.jsqlparser.statement.update.Update;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * 鏁版嵁鏉冮檺鎷︽埅鍣�
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+public class PlusDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
+
+    private final PlusDataPermissionHandler dataPermissionHandler = new PlusDataPermissionHandler();
+
+    @Override
+    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
+        // 妫�鏌ュ拷鐣ユ敞瑙�
+        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
+            return;
+        }
+        // 妫�鏌ユ槸鍚︽棤鏁� 鏃犳暟鎹潈闄愭敞瑙�
+        if (dataPermissionHandler.isInvalid(ms.getId())) {
+            return;
+        }
+        // 瑙f瀽 sql 鍒嗛厤瀵瑰簲鏂规硶
+        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
+        mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));
+    }
+
+    @Override
+    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
+        PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
+        MappedStatement ms = mpSh.mappedStatement();
+        SqlCommandType sct = ms.getSqlCommandType();
+        if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
+            if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
+                return;
+            }
+            PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
+            mpBs.sql(parserMulti(mpBs.sql(), ms.getId()));
+        }
+    }
+
+    @Override
+    protected void processSelect(Select select, int index, String sql, Object obj) {
+        SelectBody selectBody = select.getSelectBody();
+        if (selectBody instanceof PlainSelect) {
+            this.setWhere((PlainSelect) selectBody, (String) obj);
+        } else if (selectBody instanceof SetOperationList) {
+            SetOperationList setOperationList = (SetOperationList) selectBody;
+            List<SelectBody> selectBodyList = setOperationList.getSelects();
+            selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
+        }
+    }
+
+    @Override
+    protected void processUpdate(Update update, int index, String sql, Object obj) {
+        Expression sqlSegment = dataPermissionHandler.getSqlSegment(update.getWhere(), (String) obj, false);
+        if (null != sqlSegment) {
+            update.setWhere(sqlSegment);
+        }
+    }
+
+    @Override
+    protected void processDelete(Delete delete, int index, String sql, Object obj) {
+        Expression sqlSegment = dataPermissionHandler.getSqlSegment(delete.getWhere(), (String) obj, false);
+        if (null != sqlSegment) {
+            delete.setWhere(sqlSegment);
+        }
+    }
+
+    /**
+     * 璁剧疆 where 鏉′欢
+     *
+     * @param plainSelect       鏌ヨ瀵硅薄
+     * @param mappedStatementId 鎵ц鏂规硶id
+     */
+    protected void setWhere(PlainSelect plainSelect, String mappedStatementId) {
+        Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), mappedStatementId, true);
+        if (null != sqlSegment) {
+            plainSelect.setWhere(sqlSegment);
+        }
+    }
+
+}
+
diff --git a/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..dbcd9a1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.mybatis.config.MybatisPlusConfig
diff --git a/ruoyi-common/ruoyi-common-oss/pom.xml b/ruoyi-common/ruoyi-common-oss/pom.xml
new file mode 100644
index 0000000..0311fa4
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/pom.xml
@@ -0,0 +1,36 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-oss</artifactId>
+
+    <description>
+        ruoyi-common-oss oss鏈嶅姟
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.amazonaws</groupId>
+            <artifactId>aws-java-sdk-s3</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java
new file mode 100644
index 0000000..50a3292
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java
@@ -0,0 +1,38 @@
+package com.ruoyi.common.oss.constant;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 瀵硅薄瀛樺偍甯搁噺
+ *
+ * @author Lion Li
+ */
+public interface OssConstant {
+
+    /**
+     * 榛樿閰嶇疆KEY
+     */
+    String DEFAULT_CONFIG_KEY = "sys_oss:default_config";
+
+    /**
+     * 棰勮鍒楄〃璧勬簮寮�鍏矺ey
+     */
+    String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
+
+    /**
+     * 绯荤粺鏁版嵁ids
+     */
+    List<Long> SYSTEM_DATA_IDS = Arrays.asList(1L, 2L, 3L, 4L);
+
+    /**
+     * 浜戞湇鍔″晢
+     */
+    String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu", "obs"};
+
+    /**
+     * https 鐘舵��
+     */
+    String IS_HTTPS = "Y";
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/core/OssClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/core/OssClient.java
new file mode 100644
index 0000000..0e5e881
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/core/OssClient.java
@@ -0,0 +1,240 @@
+package com.ruoyi.common.oss.core;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.IdUtil;
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.HttpMethod;
+import com.amazonaws.Protocol;
+import com.amazonaws.auth.AWSCredentials;
+import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3Client;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.amazonaws.services.s3.model.*;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.constant.OssConstant;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.AccessPolicyType;
+import com.ruoyi.common.oss.enumd.PolicyType;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Date;
+
+/**
+ * S3 瀛樺偍鍗忚 鎵�鏈夊吋瀹筍3鍗忚鐨勪簯鍘傚晢鍧囨敮鎸�
+ * 闃块噷浜� 鑵捐浜� 涓冪墰浜� minio
+ *
+ * @author Lion Li
+ */
+public class OssClient {
+
+    private final String configKey;
+
+    private final OssProperties properties;
+
+    private final AmazonS3 client;
+
+    public OssClient(String configKey, OssProperties ossProperties) {
+        this.configKey = configKey;
+        this.properties = ossProperties;
+        try {
+            AwsClientBuilder.EndpointConfiguration endpointConfig =
+                new AwsClientBuilder.EndpointConfiguration(properties.getEndpoint(), properties.getRegion());
+
+            AWSCredentials credentials = new BasicAWSCredentials(properties.getAccessKey(), properties.getSecretKey());
+            AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);
+            ClientConfiguration clientConfig = new ClientConfiguration();
+            if (OssConstant.IS_HTTPS.equals(properties.getIsHttps())) {
+                clientConfig.setProtocol(Protocol.HTTPS);
+            } else {
+                clientConfig.setProtocol(Protocol.HTTP);
+            }
+            AmazonS3ClientBuilder build = AmazonS3Client.builder()
+                .withEndpointConfiguration(endpointConfig)
+                .withClientConfiguration(clientConfig)
+                .withCredentials(credentialsProvider)
+                .disableChunkedEncoding();
+            if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) {
+                // minio 浣跨敤https闄愬埗浣跨敤鍩熷悕璁块棶 闇�瑕佹閰嶇疆 绔欑偣濉煙鍚�
+                build.enablePathStyleAccess();
+            }
+            this.client = build.build();
+
+            createBucket();
+        } catch (Exception e) {
+            if (e instanceof OssException) {
+                throw e;
+            }
+            throw new OssException("閰嶇疆閿欒! 璇锋鏌ョ郴缁熼厤缃�:[" + e.getMessage() + "]");
+        }
+    }
+
+    public void createBucket() {
+        try {
+            String bucketName = properties.getBucketName();
+            if (client.doesBucketExistV2(bucketName)) {
+                return;
+            }
+            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+            AccessPolicyType accessPolicy = getAccessPolicy();
+            createBucketRequest.setCannedAcl(accessPolicy.getAcl());
+            client.createBucket(createBucketRequest);
+            client.setBucketPolicy(bucketName, getPolicy(bucketName, accessPolicy.getPolicyType()));
+        } catch (Exception e) {
+            throw new OssException("鍒涘缓Bucket澶辫触, 璇锋牳瀵归厤缃俊鎭�:[" + e.getMessage() + "]");
+        }
+    }
+
+    public UploadResult upload(byte[] data, String path, String contentType) {
+        return upload(new ByteArrayInputStream(data), path, contentType);
+    }
+
+    public UploadResult upload(InputStream inputStream, String path, String contentType) {
+        if (!(inputStream instanceof ByteArrayInputStream)) {
+            inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
+        }
+        try {
+            ObjectMetadata metadata = new ObjectMetadata();
+            metadata.setContentType(contentType);
+            metadata.setContentLength(inputStream.available());
+            PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata);
+            // 璁剧疆涓婁紶瀵硅薄鐨� Acl 涓哄叕鍏辫
+            putObjectRequest.setCannedAcl(getAccessPolicy().getAcl());
+            client.putObject(putObjectRequest);
+        } catch (Exception e) {
+            throw new OssException("涓婁紶鏂囦欢澶辫触锛岃妫�鏌ラ厤缃俊鎭�:[" + e.getMessage() + "]");
+        }
+        return UploadResult.builder().url(getUrl() + "/" + path).filename(path).build();
+    }
+
+    public void delete(String path) {
+        path = path.replace(getUrl() + "/", "");
+        try {
+            client.deleteObject(properties.getBucketName(), path);
+        } catch (Exception e) {
+            throw new OssException("鍒犻櫎鏂囦欢澶辫触锛岃妫�鏌ラ厤缃俊鎭�:[" + e.getMessage() + "]");
+        }
+    }
+
+    public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
+        return upload(data, getPath(properties.getPrefix(), suffix), contentType);
+    }
+
+    public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
+        return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍏冩暟鎹�
+     *
+     * @param path 瀹屾暣鏂囦欢璺緞
+     */
+    public ObjectMetadata getObjectMetadata(String path) {
+        path = path.replace(getUrl() + "/", "");
+        S3Object object = client.getObject(properties.getBucketName(), path);
+        return object.getObjectMetadata();
+    }
+
+    public InputStream getObjectContent(String path) {
+        path = path.replace(getUrl() + "/", "");
+        S3Object object = client.getObject(properties.getBucketName(), path);
+        return object.getObjectContent();
+    }
+
+    public String getUrl() {
+        String domain = properties.getDomain();
+        String endpoint = properties.getEndpoint();
+        String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://";
+        // 浜戞湇鍔″晢鐩存帴杩斿洖
+        if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) {
+            if (StringUtils.isNotBlank(domain)) {
+                return header + domain;
+            }
+            return header + properties.getBucketName() + "." + endpoint;
+        }
+        // minio 鍗曠嫭澶勭悊
+        if (StringUtils.isNotBlank(domain)) {
+            return header + domain + "/" + properties.getBucketName();
+        }
+        return header + endpoint + "/" + properties.getBucketName();
+    }
+
+    public String getPath(String prefix, String suffix) {
+        // 鐢熸垚uuid
+        String uuid = IdUtil.fastSimpleUUID();
+        // 鏂囦欢璺緞
+        String path = DateUtils.datePath() + "/" + uuid;
+        if (StringUtils.isNotBlank(prefix)) {
+            path = prefix + "/" + path;
+        }
+        return path + suffix;
+    }
+
+
+    public String getConfigKey() {
+        return configKey;
+    }
+
+    public String getPrivateUrl(String objectKey, Integer second) {
+        GeneratePresignedUrlRequest generatePresignedUrlRequest =
+            new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
+                .withMethod(HttpMethod.GET)
+                .withExpiration(new Date(System.currentTimeMillis() + 1000L * second));
+        URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
+        return url.toString();
+    }
+
+    /**
+     * 鑾峰彇褰撳墠妗舵潈闄愮被鍨�
+     *
+     * @return 褰撳墠妗舵潈闄愮被鍨媍ode
+     */
+    public AccessPolicyType getAccessPolicy() {
+        return AccessPolicyType.getByType(properties.getAccessPolicy());
+    }
+
+    private static String getPolicy(String bucketName, PolicyType policyType) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n");
+        if (policyType == PolicyType.WRITE) {
+            builder.append("\"s3:GetBucketLocation\",\n\"s3:ListBucketMultipartUploads\"\n");
+        } else if (policyType == PolicyType.READ_WRITE) {
+            builder.append("\"s3:GetBucketLocation\",\n\"s3:ListBucket\",\n\"s3:ListBucketMultipartUploads\"\n");
+        } else {
+            builder.append("\"s3:GetBucketLocation\"\n");
+        }
+        builder.append("],\n\"Effect\": \"Allow\",\n\"Principal\": \"*\",\n\"Resource\": \"arn:aws:s3:::");
+        builder.append(bucketName);
+        builder.append("\"\n},\n");
+        if (policyType == PolicyType.READ) {
+            builder.append("{\n\"Action\": [\n\"s3:ListBucket\"\n],\n\"Effect\": \"Deny\",\n\"Principal\": \"*\",\n\"Resource\": \"arn:aws:s3:::");
+            builder.append(bucketName);
+            builder.append("\"\n},\n");
+        }
+        builder.append("{\n\"Action\": ");
+        switch (policyType) {
+            case WRITE:
+                builder.append("[\n\"s3:AbortMultipartUpload\",\n\"s3:DeleteObject\",\n\"s3:ListMultipartUploadParts\",\n\"s3:PutObject\"\n],\n");
+                break;
+            case READ_WRITE:
+                builder.append("[\n\"s3:AbortMultipartUpload\",\n\"s3:DeleteObject\",\n\"s3:GetObject\",\n\"s3:ListMultipartUploadParts\",\n\"s3:PutObject\"\n],\n");
+                break;
+            default:
+                builder.append("\"s3:GetObject\",\n");
+                break;
+        }
+        builder.append("\"Effect\": \"Allow\",\n\"Principal\": \"*\",\n\"Resource\": \"arn:aws:s3:::");
+        builder.append(bucketName);
+        builder.append("/*\"\n}\n],\n\"Version\": \"2012-10-17\"\n}\n");
+        return builder.toString();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java
new file mode 100644
index 0000000..fd2e7fc
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.oss.entity;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 涓婁紶杩斿洖浣�
+ *
+ * @author Lion Li
+ */
+@Data
+@Builder
+public class UploadResult {
+
+    /**
+     * 鏂囦欢璺緞
+     */
+    private String url;
+
+    /**
+     * 鏂囦欢鍚�
+     */
+    private String filename;
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/AccessPolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/AccessPolicyType.java
new file mode 100644
index 0000000..140f67a
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/AccessPolicyType.java
@@ -0,0 +1,55 @@
+package com.ruoyi.common.oss.enumd;
+
+import com.amazonaws.services.s3.model.CannedAccessControlList;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 妗惰闂瓥鐣ラ厤缃�
+ *
+ * @author 闄堣碀
+ */
+@Getter
+@AllArgsConstructor
+public enum AccessPolicyType {
+
+    /**
+     * private
+     */
+    PRIVATE("0", CannedAccessControlList.Private, PolicyType.WRITE),
+
+    /**
+     * public
+     */
+    PUBLIC("1", CannedAccessControlList.PublicRead, PolicyType.READ),
+
+    /**
+     * custom
+     */
+    CUSTOM("2",CannedAccessControlList.PublicRead, PolicyType.READ);
+
+    /**
+     * 妗� 鏉冮檺绫诲瀷
+     */
+    private final String type;
+
+    /**
+     * 鏂囦欢瀵硅薄 鏉冮檺绫诲瀷
+     */
+    private final CannedAccessControlList acl;
+
+    /**
+     * 妗剁瓥鐣ョ被鍨�
+     */
+    private final PolicyType policyType;
+
+    public static AccessPolicyType getByType(String type) {
+        for (AccessPolicyType value : values()) {
+            if (value.getType().equals(type)) {
+                return value;
+            }
+        }
+        throw new RuntimeException("'type' not found By " + type);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java
new file mode 100644
index 0000000..c019d3b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.oss.enumd;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * minio绛栫暐閰嶇疆
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum PolicyType {
+
+    /**
+     * 鍙
+     */
+    READ("read-only"),
+
+    /**
+     * 鍙啓
+     */
+    WRITE("write-only"),
+
+    /**
+     * 璇诲啓
+     */
+    READ_WRITE("read-write");
+
+    /**
+     * 绫诲瀷
+     */
+    private final String type;
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java
new file mode 100644
index 0000000..cfc7520
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.oss.exception;
+
+import java.io.Serial;
+
+/**
+ * OSS寮傚父绫�
+ *
+ * @author Lion Li
+ */
+public class OssException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public OssException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java
new file mode 100644
index 0000000..a47e949
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.oss.factory;
+
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.constant.OssConstant;
+import com.ruoyi.common.oss.core.OssClient;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 鏂囦欢涓婁紶Factory
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class OssFactory {
+
+    private static final Map<String, OssClient> CLIENT_CACHE = new ConcurrentHashMap<>();
+
+    /**
+     * 鍒濆鍖栧伐鍘�
+     */
+    public static void init() {
+        log.info("鍒濆鍖朞SS宸ュ巶");
+        RedisUtils.subscribe(OssConstant.DEFAULT_CONFIG_KEY, String.class, configKey -> {
+            OssClient client = getClient(configKey);
+            // 鏈垵濮嬪寲涓嶅鐞�
+            if (client != null) {
+                refresh(configKey);
+                log.info("璁㈤槄鍒锋柊OSS閰嶇疆 => " + configKey);
+            }
+        });
+    }
+
+    /**
+     * 鑾峰彇榛樿瀹炰緥
+     */
+    public static OssClient instance() {
+        // 鑾峰彇redis 榛樿绫诲瀷
+        String configKey = RedisUtils.getCacheObject(OssConstant.DEFAULT_CONFIG_KEY);
+        if (StringUtils.isEmpty(configKey)) {
+            throw new OssException("鏂囦欢瀛樺偍鏈嶅姟绫诲瀷鏃犳硶鎵惧埌!");
+        }
+        return instance(configKey);
+    }
+
+    /**
+     * 鏍规嵁绫诲瀷鑾峰彇瀹炰緥
+     */
+    public static OssClient instance(String configKey) {
+        OssClient client = getClient(configKey);
+        if (client == null) {
+            refresh(configKey);
+            return getClient(configKey);
+        }
+        return client;
+    }
+
+    private static void refresh(String configKey) {
+        String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey);
+        if (json == null) {
+            throw new OssException("绯荤粺寮傚父, '" + configKey + "'閰嶇疆淇℃伅涓嶅瓨鍦�!");
+        }
+        OssProperties properties = JsonUtils.parseObject(json, OssProperties.class);
+        CLIENT_CACHE.put(configKey, new OssClient(configKey, properties));
+    }
+
+    private static OssClient getClient(String configKey) {
+        return CLIENT_CACHE.get(configKey);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java
new file mode 100644
index 0000000..bf7ab2f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java
@@ -0,0 +1,58 @@
+package com.ruoyi.common.oss.properties;
+
+import lombok.Data;
+
+/**
+ * OSS瀵硅薄瀛樺偍 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+public class OssProperties {
+
+    /**
+     * 璁块棶绔欑偣
+     */
+    private String endpoint;
+
+    /**
+     * 鑷畾涔夊煙鍚�
+     */
+    private String domain;
+
+    /**
+     * 鍓嶇紑
+     */
+    private String prefix;
+
+    /**
+     * ACCESS_KEY
+     */
+    private String accessKey;
+
+    /**
+     * SECRET_KEY
+     */
+    private String secretKey;
+
+    /**
+     * 瀛樺偍绌洪棿鍚�
+     */
+    private String bucketName;
+
+    /**
+     * 瀛樺偍鍖哄煙
+     */
+    private String region;
+
+    /**
+     * 鏄惁https锛圷=鏄�,N=鍚︼級
+     */
+    private String isHttps;
+
+    /**
+     * 妗舵潈闄愮被鍨�(0private 1public 2custom)
+     */
+    private String accessPolicy;
+
+}
diff --git a/ruoyi-common/ruoyi-common-ratelimiter/pom.xml b/ruoyi-common/ruoyi-common-ratelimiter/pom.xml
new file mode 100644
index 0000000..d4aa966
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-ratelimiter/pom.xml
@@ -0,0 +1,31 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-ratelimiter</artifactId>
+
+    <description>
+        ruoyi-common-ratelimiter 闄愭祦鍔熻兘
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/annotation/RateLimiter.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/annotation/RateLimiter.java
new file mode 100644
index 0000000..b5bd284
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/annotation/RateLimiter.java
@@ -0,0 +1,36 @@
+package com.ruoyi.common.ratelimiter.annotation;
+
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.ratelimiter.enums.LimitType;
+
+import java.lang.annotation.*;
+
+/**
+ * 闄愭祦娉ㄨВ
+ *
+ * @author Lion Li
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RateLimiter {
+    /**
+     * 闄愭祦key
+     */
+    String key() default CacheConstants.RATE_LIMIT_KEY;
+
+    /**
+     * 闄愭祦鏃堕棿,鍗曚綅绉�
+     */
+    int time() default 60;
+
+    /**
+     * 闄愭祦娆℃暟
+     */
+    int count() default 100;
+
+    /**
+     * 闄愭祦绫诲瀷
+     */
+    LimitType limitType() default LimitType.DEFAULT;
+}
diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/aspectj/RateLimiterAspect.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/aspectj/RateLimiterAspect.java
new file mode 100644
index 0000000..b313aaa
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/aspectj/RateLimiterAspect.java
@@ -0,0 +1,64 @@
+package com.ruoyi.common.ratelimiter.aspectj;
+
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.ratelimiter.annotation.RateLimiter;
+import com.ruoyi.common.ratelimiter.enums.LimitType;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.redisson.api.RateType;
+
+import java.lang.reflect.Method;
+
+/**
+ * 闄愭祦澶勭悊
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@Aspect
+public class RateLimiterAspect {
+
+    @Before("@annotation(rateLimiter)")
+    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
+        int time = rateLimiter.time();
+        int count = rateLimiter.count();
+        String combineKey = getCombineKey(rateLimiter, point);
+        try {
+            RateType rateType = RateType.OVERALL;
+            if (rateLimiter.limitType() == LimitType.CLUSTER) {
+                rateType = RateType.PER_CLIENT;
+            }
+            long number = RedisUtils.rateLimiter(combineKey, rateType, count, time);
+            if (number == -1) {
+                throw new ServiceException(MessageUtils.message("rate.limiter.message"));
+            }
+            log.info("闄愬埗浠ょ墝 => {}, 鍓╀綑浠ょ墝 => {}, 缂撳瓨key => '{}'", count, number, combineKey);
+        } catch (ServiceException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException("鏈嶅姟鍣ㄩ檺娴佸紓甯革紝璇风◢鍊欏啀璇�");
+        }
+    }
+
+    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
+        StringBuilder stringBuffer = new StringBuilder(rateLimiter.key());
+        if (rateLimiter.limitType() == LimitType.IP) {
+            // 鑾峰彇璇锋眰ip
+            stringBuffer.append(ServletUtils.getClientIP()).append("-");
+        } else if (rateLimiter.limitType() == LimitType.CLUSTER) {
+            // 鑾峰彇瀹㈡埛绔疄渚媔d
+            stringBuffer.append(RedisUtils.getClient().getId()).append("-");
+        }
+        MethodSignature signature = (MethodSignature) point.getSignature();
+        Method method = signature.getMethod();
+        Class<?> targetClass = method.getDeclaringClass();
+        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
+        return stringBuffer.toString();
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/config/RateLimiterConfig.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/config/RateLimiterConfig.java
new file mode 100644
index 0000000..f55a1f7
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/config/RateLimiterConfig.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.ratelimiter.config;
+
+import com.ruoyi.common.ratelimiter.aspectj.RateLimiterAspect;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.redis.connection.RedisConfiguration;
+
+/**
+ * @author guangxin
+ * @date 2023/1/18
+ */
+@AutoConfiguration(after = RedisConfiguration.class)
+public class RateLimiterConfig {
+
+    @Bean
+    public RateLimiterAspect rateLimiterAspect() {
+        return new RateLimiterAspect();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/enums/LimitType.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/enums/LimitType.java
new file mode 100644
index 0000000..1ff05d1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/com/ruoyi/common/ratelimiter/enums/LimitType.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.ratelimiter.enums;
+
+/**
+ * 闄愭祦绫诲瀷
+ *
+ * @author ruoyi
+ */
+
+public enum LimitType {
+    /**
+     * 榛樿绛栫暐鍏ㄥ眬闄愭祦
+     */
+    DEFAULT,
+
+    /**
+     * 鏍规嵁璇锋眰鑰匢P杩涜闄愭祦
+     */
+    IP,
+
+    /**
+     * 瀹炰緥闄愭祦(闆嗙兢澶氬悗绔疄渚�)
+     */
+    CLUSTER
+}
diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-ratelimiter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..68afe55
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.ratelimiter.config.RateLimiterConfig
diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml
new file mode 100644
index 0000000..9e2d9c6
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/pom.xml
@@ -0,0 +1,38 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-redis</artifactId>
+
+    <description>
+        ruoyi-common-redis 缂撳瓨鏈嶅姟
+    </description>
+
+    <dependencies>
+        <!-- RuoYi Common Core-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <!--redisson-->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java
new file mode 100644
index 0000000..1cbb6eb
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/RedisConfig.java
@@ -0,0 +1,130 @@
+package com.ruoyi.common.redis.config;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.redis.config.properties.RedissonProperties;
+import com.ruoyi.common.redis.handler.KeyPrefixHandler;
+import com.ruoyi.common.redis.manager.PlusSpringCacheManager;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.codec.JsonJacksonCodec;
+import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * redis閰嶇疆
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@AutoConfiguration
+@EnableCaching
+@EnableConfigurationProperties(RedissonProperties.class)
+public class RedisConfig {
+
+    @Autowired
+    private RedissonProperties redissonProperties;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Bean
+    public RedissonAutoConfigurationCustomizer redissonCustomizer() {
+        return config -> {
+            config.setThreads(redissonProperties.getThreads())
+                .setNettyThreads(redissonProperties.getNettyThreads())
+                .setCodec(new JsonJacksonCodec(objectMapper));
+            RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
+            if (ObjectUtil.isNotNull(singleServerConfig)) {
+                // 浣跨敤鍗曟満妯″紡
+                config.useSingleServer()
+                    //璁剧疆redis key鍓嶇紑
+                    .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
+                    .setTimeout(singleServerConfig.getTimeout())
+                    .setClientName(singleServerConfig.getClientName())
+                    .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
+                    .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
+                    .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
+                    .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
+            }
+            // 闆嗙兢閰嶇疆鏂瑰紡 鍙傝�冧笅鏂规敞閲�
+            RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
+            if (ObjectUtil.isNotNull(clusterServersConfig)) {
+                config.useClusterServers()
+                    //璁剧疆redis key鍓嶇紑
+                    .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
+                    .setTimeout(clusterServersConfig.getTimeout())
+                    .setClientName(clusterServersConfig.getClientName())
+                    .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
+                    .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
+                    .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
+                    .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
+                    .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
+                    .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
+                    .setReadMode(clusterServersConfig.getReadMode())
+                    .setSubscriptionMode(clusterServersConfig.getSubscriptionMode());
+            }
+            log.info("鍒濆鍖� redis 閰嶇疆");
+        };
+    }
+
+    /**
+     * 鑷畾涔夌紦瀛樼鐞嗗櫒 鏁村悎spring-cache
+     */
+    @Bean
+    public CacheManager cacheManager() {
+        return new PlusSpringCacheManager();
+    }
+
+    /**
+     * redis闆嗙兢閰嶇疆 yml
+     *
+     * --- # redis 闆嗙兢閰嶇疆(鍗曟満涓庨泦缇ゅ彧鑳藉紑鍚竴涓彟涓�涓渶瑕佹敞閲婃帀)
+     * spring:
+     *   redis:
+     *     cluster:
+     *       nodes:
+     *         - 192.168.0.100:6379
+     *         - 192.168.0.101:6379
+     *         - 192.168.0.102:6379
+     *     # 瀵嗙爜
+     *     password:
+     *     # 杩炴帴瓒呮椂鏃堕棿
+     *     timeout: 10s
+     *     # 鏄惁寮�鍚痵sl
+     *     ssl: false
+     *
+     * redisson:
+     *   # 绾跨▼姹犳暟閲�
+     *   threads: 16
+     *   # Netty绾跨▼姹犳暟閲�
+     *   nettyThreads: 32
+     *   # 闆嗙兢閰嶇疆
+     *   clusterServersConfig:
+     *     # 瀹㈡埛绔悕绉�
+     *     clientName: ${ruoyi.name}
+     *     # master鏈�灏忕┖闂茶繛鎺ユ暟
+     *     masterConnectionMinimumIdleSize: 32
+     *     # master杩炴帴姹犲ぇ灏�
+     *     masterConnectionPoolSize: 64
+     *     # slave鏈�灏忕┖闂茶繛鎺ユ暟
+     *     slaveConnectionMinimumIdleSize: 32
+     *     # slave杩炴帴姹犲ぇ灏�
+     *     slaveConnectionPoolSize: 64
+     *     # 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
+     *     idleConnectionTimeout: 10000
+     *     # 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
+     *     timeout: 3000
+     *     # 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
+     *     subscriptionConnectionPoolSize: 50
+     *     # 璇诲彇妯″紡
+     *     readMode: "SLAVE"
+     *     # 璁㈤槄妯″紡
+     *     subscriptionMode: "MASTER"
+     */
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java
new file mode 100644
index 0000000..e03017f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/config/properties/RedissonProperties.java
@@ -0,0 +1,137 @@
+package com.ruoyi.common.redis.config.properties;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.redisson.config.ReadMode;
+import org.redisson.config.SubscriptionMode;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * Redisson 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "redisson")
+public class RedissonProperties {
+
+    /**
+     * redis缂撳瓨key鍓嶇紑
+     */
+    private String keyPrefix;
+
+    /**
+     * 绾跨▼姹犳暟閲�,榛樿鍊� = 褰撳墠澶勭悊鏍告暟閲� * 2
+     */
+    private int threads;
+
+    /**
+     * Netty绾跨▼姹犳暟閲�,榛樿鍊� = 褰撳墠澶勭悊鏍告暟閲� * 2
+     */
+    private int nettyThreads;
+
+    /**
+     * 鍗曟満鏈嶅姟閰嶇疆
+     */
+    private SingleServerConfig singleServerConfig;
+
+    /**
+     * 闆嗙兢鏈嶅姟閰嶇疆
+     */
+    private ClusterServersConfig clusterServersConfig;
+
+    @Data
+    @NoArgsConstructor
+    public static class SingleServerConfig {
+
+        /**
+         * 瀹㈡埛绔悕绉�
+         */
+        private String clientName;
+
+        /**
+         * 鏈�灏忕┖闂茶繛鎺ユ暟
+         */
+        private int connectionMinimumIdleSize;
+
+        /**
+         * 杩炴帴姹犲ぇ灏�
+         */
+        private int connectionPoolSize;
+
+        /**
+         * 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
+         */
+        private int idleConnectionTimeout;
+
+        /**
+         * 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
+         */
+        private int timeout;
+
+        /**
+         * 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
+         */
+        private int subscriptionConnectionPoolSize;
+
+    }
+
+    @Data
+    @NoArgsConstructor
+    public static class ClusterServersConfig {
+
+        /**
+         * 瀹㈡埛绔悕绉�
+         */
+        private String clientName;
+
+        /**
+         * master鏈�灏忕┖闂茶繛鎺ユ暟
+         */
+        private int masterConnectionMinimumIdleSize;
+
+        /**
+         * master杩炴帴姹犲ぇ灏�
+         */
+        private int masterConnectionPoolSize;
+
+        /**
+         * slave鏈�灏忕┖闂茶繛鎺ユ暟
+         */
+        private int slaveConnectionMinimumIdleSize;
+
+        /**
+         * slave杩炴帴姹犲ぇ灏�
+         */
+        private int slaveConnectionPoolSize;
+
+        /**
+         * 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
+         */
+        private int idleConnectionTimeout;
+
+        /**
+         * 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
+         */
+        private int timeout;
+
+        /**
+         * 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
+         */
+        private int subscriptionConnectionPoolSize;
+
+        /**
+         * 璇诲彇妯″紡
+         */
+        private ReadMode readMode;
+
+        /**
+         * 璁㈤槄妯″紡
+         */
+        private SubscriptionMode subscriptionMode;
+
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/handler/KeyPrefixHandler.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/handler/KeyPrefixHandler.java
new file mode 100644
index 0000000..ff1dbba
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/handler/KeyPrefixHandler.java
@@ -0,0 +1,50 @@
+package com.ruoyi.common.redis.handler;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import org.redisson.api.NameMapper;
+
+/**
+ * redis缂撳瓨key鍓嶇紑澶勭悊
+ *
+ * @author ye
+ * @date 2022/7/14 17:44
+ * @since 4.3.0
+ */
+public class KeyPrefixHandler implements NameMapper {
+
+    private final String keyPrefix;
+
+    public KeyPrefixHandler(String keyPrefix) {
+        //鍓嶇紑涓虹┖ 鍒欒繑鍥炵┖鍓嶇紑
+        this.keyPrefix = StringUtils.isBlank(keyPrefix) ? "" : keyPrefix + ":";
+    }
+
+    /**
+     * 澧炲姞鍓嶇紑
+     */
+    @Override
+    public String map(String name) {
+        if (StringUtils.isBlank(name)) {
+            return null;
+        }
+        if (StringUtils.isNotBlank(keyPrefix) && !name.startsWith(keyPrefix)) {
+            return keyPrefix + name;
+        }
+        return name;
+    }
+
+    /**
+     * 鍘婚櫎鍓嶇紑
+     */
+    @Override
+    public String unmap(String name) {
+        if (StringUtils.isBlank(name)) {
+            return null;
+        }
+        if (StringUtils.isNotBlank(keyPrefix) && name.startsWith(keyPrefix)) {
+            return name.substring(keyPrefix.length());
+        }
+        return name;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/manager/PlusSpringCacheManager.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/manager/PlusSpringCacheManager.java
new file mode 100644
index 0000000..736f0da
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/manager/PlusSpringCacheManager.java
@@ -0,0 +1,191 @@
+/**
+ * Copyright (c) 2013-2021 Nikita Koksharov
+ *
+ * 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
+ *
+ *    http://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 com.ruoyi.common.redis.manager;
+
+import com.ruoyi.common.redis.utils.RedisUtils;
+import org.redisson.api.RMap;
+import org.redisson.api.RMapCache;
+import org.redisson.spring.cache.CacheConfig;
+import org.redisson.spring.cache.RedissonCache;
+import org.springframework.boot.convert.DurationStyle;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
+import org.springframework.util.StringUtils;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * A {@link org.springframework.cache.CacheManager} implementation
+ * backed by Redisson instance.
+ * <p>
+ * 淇敼 RedissonSpringCacheManager 婧愮爜
+ * 閲嶅啓 cacheName 澶勭悊鏂规硶 鏀寔澶氬弬鏁�
+ *
+ * @author Nikita Koksharov
+ *
+ */
+@SuppressWarnings("unchecked")
+public class PlusSpringCacheManager implements CacheManager {
+
+    private boolean dynamic = true;
+
+    private boolean allowNullValues = true;
+
+    private boolean transactionAware = true;
+
+    Map<String, CacheConfig> configMap = new ConcurrentHashMap<>();
+    ConcurrentMap<String, Cache> instanceMap = new ConcurrentHashMap<>();
+
+    /**
+     * Creates CacheManager supplied by Redisson instance
+     */
+    public PlusSpringCacheManager() {
+    }
+
+
+    /**
+     * Defines possibility of storing {@code null} values.
+     * <p>
+     * Default is <code>true</code>
+     *
+     * @param allowNullValues stores if <code>true</code>
+     */
+    public void setAllowNullValues(boolean allowNullValues) {
+        this.allowNullValues = allowNullValues;
+    }
+
+    /**
+     * Defines if cache aware of Spring-managed transactions.
+     * If {@code true} put/evict operations are executed only for successful transaction in after-commit phase.
+     * <p>
+     * Default is <code>false</code>
+     *
+     * @param transactionAware cache is transaction aware if <code>true</code>
+     */
+    public void setTransactionAware(boolean transactionAware) {
+        this.transactionAware = transactionAware;
+    }
+
+    /**
+     * Defines 'fixed' cache names.
+     * A new cache instance will not be created in dynamic for non-defined names.
+     * <p>
+     * `null` parameter setups dynamic mode
+     *
+     * @param names of caches
+     */
+    public void setCacheNames(Collection<String> names) {
+        if (names != null) {
+            for (String name : names) {
+                getCache(name);
+            }
+            dynamic = false;
+        } else {
+            dynamic = true;
+        }
+    }
+
+    /**
+     * Set cache config mapped by cache name
+     *
+     * @param config object
+     */
+    public void setConfig(Map<String, ? extends CacheConfig> config) {
+        this.configMap = (Map<String, CacheConfig>) config;
+    }
+
+    protected CacheConfig createDefaultConfig() {
+        return new CacheConfig();
+    }
+
+    @Override
+    public Cache getCache(String name) {
+        Cache cache = instanceMap.get(name);
+        if (cache != null) {
+            return cache;
+        }
+        if (!dynamic) {
+            return cache;
+        }
+
+        CacheConfig config = configMap.get(name);
+        if (config == null) {
+            config = createDefaultConfig();
+            configMap.put(name, config);
+        }
+
+        // 閲嶅啓 cacheName 鏀寔澶氬弬鏁�
+        String[] array = StringUtils.delimitedListToStringArray(name, "#");
+        name = array[0];
+        if (array.length > 1) {
+            config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis());
+        }
+        if (array.length > 2) {
+            config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis());
+        }
+        if (array.length > 3) {
+            config.setMaxSize(Integer.parseInt(array[3]));
+        }
+
+        if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {
+            return createMap(name, config);
+        }
+
+        return createMapCache(name, config);
+    }
+
+    private Cache createMap(String name, CacheConfig config) {
+        RMap<Object, Object> map = RedisUtils.getClient().getMap(name);
+
+        Cache cache = new RedissonCache(map, allowNullValues);
+        if (transactionAware) {
+            cache = new TransactionAwareCacheDecorator(cache);
+        }
+        Cache oldCache = instanceMap.putIfAbsent(name, cache);
+        if (oldCache != null) {
+            cache = oldCache;
+        }
+        return cache;
+    }
+
+    private Cache createMapCache(String name, CacheConfig config) {
+        RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);
+
+        Cache cache = new RedissonCache(map, config, allowNullValues);
+        if (transactionAware) {
+            cache = new TransactionAwareCacheDecorator(cache);
+        }
+        Cache oldCache = instanceMap.putIfAbsent(name, cache);
+        if (oldCache != null) {
+            cache = oldCache;
+        } else {
+            map.setMaxSize(config.getMaxSize());
+        }
+        return cache;
+    }
+
+    @Override
+    public Collection<String> getCacheNames() {
+        return Collections.unmodifiableSet(configMap.keySet());
+    }
+
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/CacheUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/CacheUtils.java
new file mode 100644
index 0000000..e953d03
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/CacheUtils.java
@@ -0,0 +1,75 @@
+package com.ruoyi.common.redis.utils;
+
+import com.ruoyi.common.core.utils.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.redisson.api.RMap;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+
+import java.util.Set;
+
+/**
+ * 缂撳瓨鎿嶄綔宸ュ叿绫� {@link }
+ *
+ * @author Michelle.Chung
+ * @date 2022/8/13
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@SuppressWarnings(value = {"unchecked"})
+public class CacheUtils {
+
+    private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);
+
+    /**
+     * 鑾峰彇缂撳瓨缁勫唴鎵�鏈夌殑KEY
+     *
+     * @param cacheNames 缂撳瓨缁勫悕绉�
+     */
+    public static Set<Object> keys(String cacheNames) {
+        RMap<Object, Object> rmap = (RMap<Object, Object>) CACHE_MANAGER.getCache(cacheNames).getNativeCache();
+        return rmap.keySet();
+    }
+
+    /**
+     * 鑾峰彇缂撳瓨鍊�
+     *
+     * @param cacheNames 缂撳瓨缁勫悕绉�
+     * @param key        缂撳瓨key
+     */
+    public static <T> T get(String cacheNames, Object key) {
+        Cache.ValueWrapper wrapper = CACHE_MANAGER.getCache(cacheNames).get(key);
+        return wrapper != null ? (T) wrapper.get() : null;
+    }
+
+    /**
+     * 淇濆瓨缂撳瓨鍊�
+     *
+     * @param cacheNames 缂撳瓨缁勫悕绉�
+     * @param key        缂撳瓨key
+     * @param value      缂撳瓨鍊�
+     */
+    public static void put(String cacheNames, Object key, Object value) {
+        CACHE_MANAGER.getCache(cacheNames).put(key, value);
+    }
+
+    /**
+     * 鍒犻櫎缂撳瓨鍊�
+     *
+     * @param cacheNames 缂撳瓨缁勫悕绉�
+     * @param key        缂撳瓨key
+     */
+    public static void evict(String cacheNames, Object key) {
+        CACHE_MANAGER.getCache(cacheNames).evict(key);
+    }
+
+    /**
+     * 娓呯┖缂撳瓨鍊�
+     *
+     * @param cacheNames 缂撳瓨缁勫悕绉�
+     */
+    public static void clear(String cacheNames) {
+        CACHE_MANAGER.getCache(cacheNames).clear();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/QueueUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/QueueUtils.java
new file mode 100644
index 0000000..81e2105
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/QueueUtils.java
@@ -0,0 +1,180 @@
+package com.ruoyi.common.redis.utils;
+
+import com.ruoyi.common.core.utils.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.redisson.api.*;
+
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * 鍒嗗竷寮忛槦鍒楀伐鍏�
+ * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
+ * 瑕佹眰 redis 5.X 浠ヤ笂
+ *
+ * @author Lion Li
+ * @version 3.6.0 鏂板
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class QueueUtils {
+
+    private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
+
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疄渚�
+     */
+    public static RedissonClient getClient() {
+        return CLIENT;
+    }
+
+    /**
+     * 娣诲姞鏅�氶槦鍒楁暟鎹�
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param data      鏁版嵁
+     */
+    public static <T> boolean addQueueObject(String queueName, T data) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.offer(data);
+    }
+
+    /**
+     * 閫氱敤鑾峰彇涓�涓槦鍒楁暟鎹� 娌℃湁鏁版嵁杩斿洖 null(涓嶆敮鎸佸欢杩熼槦鍒�)
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    public static <T> T getQueueObject(String queueName) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.poll();
+    }
+
+    /**
+     * 閫氱敤鍒犻櫎闃熷垪鏁版嵁(涓嶆敮鎸佸欢杩熼槦鍒�)
+     */
+    public static <T> boolean removeQueueObject(String queueName, T data) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.remove(data);
+    }
+
+    /**
+     * 閫氱敤閿�姣侀槦鍒� 鎵�鏈夐樆濉炵洃鍚� 鎶ラ敊(涓嶆敮鎸佸欢杩熼槦鍒�)
+     */
+    public static <T> boolean destroyQueue(String queueName) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        return queue.delete();
+    }
+
+    /**
+     * 娣诲姞寤惰繜闃熷垪鏁版嵁 榛樿姣
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param data      鏁版嵁
+     * @param time      寤惰繜鏃堕棿
+     */
+    public static <T> void addDelayedQueueObject(String queueName, T data, long time) {
+        addDelayedQueueObject(queueName, data, time, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * 娣诲姞寤惰繜闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param data      鏁版嵁
+     * @param time      寤惰繜鏃堕棿
+     * @param timeUnit  鍗曚綅
+     */
+    public static <T> void addDelayedQueueObject(String queueName, T data, long time, TimeUnit timeUnit) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
+        delayedQueue.offer(data, time, timeUnit);
+    }
+
+    /**
+     * 鑾峰彇涓�涓欢杩熼槦鍒楁暟鎹� 娌℃湁鏁版嵁杩斿洖 null
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    public static <T> T getDelayedQueueObject(String queueName) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
+        return delayedQueue.poll();
+    }
+
+    /**
+     * 鍒犻櫎寤惰繜闃熷垪鏁版嵁
+     */
+    public static <T> boolean removeDelayedQueueObject(String queueName, T data) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
+        return delayedQueue.remove(data);
+    }
+
+    /**
+     * 閿�姣佸欢杩熼槦鍒� 鎵�鏈夐樆濉炵洃鍚� 鎶ラ敊
+     */
+    public static <T> void destroyDelayedQueue(String queueName) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
+        delayedQueue.destroy();
+    }
+
+    /**
+     * 娣诲姞浼樺厛闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param data      鏁版嵁
+     */
+    public static <T> boolean addPriorityQueueObject(String queueName, T data) {
+        RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
+        return priorityBlockingQueue.offer(data);
+    }
+
+    /**
+     * 灏濊瘯璁剧疆 鏈夌晫闃熷垪 瀹归噺 鐢ㄤ簬闄愬埗鏁伴噺
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param capacity  瀹归噺
+     */
+    public static <T> boolean trySetBoundedQueueCapacity(String queueName, int capacity) {
+        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
+        return boundedBlockingQueue.trySetCapacity(capacity);
+    }
+
+    /**
+     * 灏濊瘯璁剧疆 鏈夌晫闃熷垪 瀹归噺 鐢ㄤ簬闄愬埗鏁伴噺
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param capacity  瀹归噺
+     * @param destroy   宸插瓨鍦ㄦ槸鍚﹂攢姣�
+     */
+    public static <T> boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) {
+        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
+        if (boundedBlockingQueue.isExists() && destroy) {
+            destroyQueue(queueName);
+        }
+        return boundedBlockingQueue.trySetCapacity(capacity);
+    }
+
+    /**
+     * 娣诲姞鏈夌晫闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param data      鏁版嵁
+     * @return 娣诲姞鎴愬姛 true 宸茶揪鍒扮晫闄� false
+     */
+    public static <T> boolean addBoundedQueueObject(String queueName, T data) {
+        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
+        return boundedBlockingQueue.offer(data);
+    }
+
+    /**
+     * 璁㈤槄闃诲闃熷垪(鍙闃呮墍鏈夊疄鐜扮被 渚嬪: 寤惰繜 浼樺厛 鏈夌晫 绛�)
+     */
+    public static <T> void subscribeBlockingQueue(String queueName, Consumer<T> consumer) {
+        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
+        queue.subscribeOnElements(consumer);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/RedisUtils.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/RedisUtils.java
new file mode 100644
index 0000000..b665160
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/utils/RedisUtils.java
@@ -0,0 +1,462 @@
+package com.ruoyi.common.redis.utils;
+
+import com.ruoyi.common.core.utils.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.redisson.api.*;
+
+import java.time.Duration;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * redis 宸ュ叿绫�
+ *
+ * @author Lion Li
+ * @version 3.1.0 鏂板
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+public class RedisUtils {
+
+    private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
+
+    /**
+     * 闄愭祦
+     *
+     * @param key          闄愭祦key
+     * @param rateType     闄愭祦绫诲瀷
+     * @param rate         閫熺巼
+     * @param rateInterval 閫熺巼闂撮殧
+     * @return -1 琛ㄧず澶辫触
+     */
+    public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
+        RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
+        rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
+        if (rateLimiter.tryAcquire()) {
+            return rateLimiter.availablePermits();
+        } else {
+            return -1L;
+        }
+    }
+
+    /**
+     * 鑾峰彇瀹㈡埛绔疄渚�
+     */
+    public static RedissonClient getClient() {
+        return CLIENT;
+    }
+
+    /**
+     * 鍙戝竷閫氶亾娑堟伅
+     *
+     * @param channelKey 閫氶亾key
+     * @param msg        鍙戦�佹暟鎹�
+     * @param consumer   鑷畾涔夊鐞�
+     */
+    public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
+        RTopic topic = CLIENT.getTopic(channelKey);
+        topic.publish(msg);
+        consumer.accept(msg);
+    }
+
+    public static <T> void publish(String channelKey, T msg) {
+        RTopic topic = CLIENT.getTopic(channelKey);
+        topic.publish(msg);
+    }
+
+    /**
+     * 璁㈤槄閫氶亾鎺ユ敹娑堟伅
+     *
+     * @param channelKey 閫氶亾key
+     * @param clazz      娑堟伅绫诲瀷
+     * @param consumer   鑷畾涔夊鐞�
+     */
+    public static <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
+        RTopic topic = CLIENT.getTopic(channelKey);
+        topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key   缂撳瓨鐨勯敭鍊�
+     * @param value 缂撳瓨鐨勫��
+     */
+    public static <T> void setCacheObject(final String key, final T value) {
+        setCacheObject(key, value, false);
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝淇濈暀褰撳墠瀵硅薄 TTL 鏈夋晥鏈�
+     *
+     * @param key       缂撳瓨鐨勯敭鍊�
+     * @param value     缂撳瓨鐨勫��
+     * @param isSaveTtl 鏄惁淇濈暀TTL鏈夋晥鏈�(渚嬪: set涔嬪墠ttl鍓╀綑90 set涔嬪悗杩樻槸涓�90)
+     * @since Redis 6.X 浠ヤ笂浣跨敤 setAndKeepTTL 鍏煎 5.X 鏂规
+     */
+    public static <T> void setCacheObject(final String key, final T value, final boolean isSaveTtl) {
+        RBucket<T> bucket = CLIENT.getBucket(key);
+        if (isSaveTtl) {
+            try {
+                bucket.setAndKeepTTL(value);
+            } catch (Exception e) {
+                long timeToLive = bucket.remainTimeToLive();
+                setCacheObject(key, value, Duration.ofMillis(timeToLive));
+            }
+        } else {
+            bucket.set(value);
+        }
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param value    缂撳瓨鐨勫��
+     * @param duration 鏃堕棿
+     */
+    public static <T> void setCacheObject(final String key, final T value, final Duration duration) {
+        RBatch batch = CLIENT.createBatch();
+        RBucketAsync<T> bucket = batch.getBucket(key);
+        bucket.setAsync(value);
+        bucket.expireAsync(duration);
+        batch.execute();
+    }
+
+    /**
+     * 娉ㄥ唽瀵硅薄鐩戝惉鍣�
+     * <p>
+     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param listener 鐩戝惉鍣ㄩ厤缃�
+     */
+    public static <T> void addObjectListener(final String key, final ObjectListener listener) {
+        RBucket<T> result = CLIENT.getBucket(key);
+        result.addListener(listener);
+    }
+
+    /**
+     * 璁剧疆鏈夋晥鏃堕棿
+     *
+     * @param key     Redis閿�
+     * @param timeout 瓒呮椂鏃堕棿
+     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+     */
+    public static boolean expire(final String key, final long timeout) {
+        return expire(key, Duration.ofSeconds(timeout));
+    }
+
+    /**
+     * 璁剧疆鏈夋晥鏃堕棿
+     *
+     * @param key      Redis閿�
+     * @param duration 瓒呮椂鏃堕棿
+     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+     */
+    public static boolean expire(final String key, final Duration duration) {
+        RBucket rBucket = CLIENT.getBucket(key);
+        return rBucket.expire(duration);
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞°��
+     *
+     * @param key 缂撳瓨閿��
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public static <T> T getCacheObject(final String key) {
+        RBucket<T> rBucket = CLIENT.getBucket(key);
+        return rBucket.get();
+    }
+
+    /**
+     * 鑾峰緱key鍓╀綑瀛樻椿鏃堕棿
+     *
+     * @param key 缂撳瓨閿��
+     * @return 鍓╀綑瀛樻椿鏃堕棿
+     */
+    public static <T> long getTimeToLive(final String key) {
+        RBucket<T> rBucket = CLIENT.getBucket(key);
+        return rBucket.remainTimeToLive();
+    }
+
+    /**
+     * 鍒犻櫎鍗曚釜瀵硅薄
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     */
+    public static boolean deleteObject(final String key) {
+        return CLIENT.getBucket(key).delete();
+    }
+
+    /**
+     * 鍒犻櫎闆嗗悎瀵硅薄
+     *
+     * @param collection 澶氫釜瀵硅薄
+     */
+    public static void deleteObject(final Collection collection) {
+        RBatch batch = CLIENT.createBatch();
+        collection.forEach(t -> {
+            batch.getBucket(t.toString()).deleteAsync();
+        });
+        batch.execute();
+    }
+
+    /**
+     * 妫�鏌ョ紦瀛樺璞℃槸鍚﹀瓨鍦�
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     */
+    public static boolean isExistsObject(final String key) {
+        return CLIENT.getBucket(key).isExists();
+    }
+
+    /**
+     * 缂撳瓨List鏁版嵁
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param dataList 寰呯紦瀛樼殑List鏁版嵁
+     * @return 缂撳瓨鐨勫璞�
+     */
+    public static <T> boolean setCacheList(final String key, final List<T> dataList) {
+        RList<T> rList = CLIENT.getList(key);
+        return rList.addAll(dataList);
+    }
+
+    /**
+     * 娉ㄥ唽List鐩戝惉鍣�
+     * <p>
+     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param listener 鐩戝惉鍣ㄩ厤缃�
+     */
+    public static <T> void addListListener(final String key, final ObjectListener listener) {
+        RList<T> rList = CLIENT.getList(key);
+        rList.addListener(listener);
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨刲ist瀵硅薄
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public static <T> List<T> getCacheList(final String key) {
+        RList<T> rList = CLIENT.getList(key);
+        return rList.readAll();
+    }
+
+    /**
+     * 缂撳瓨Set
+     *
+     * @param key     缂撳瓨閿��
+     * @param dataSet 缂撳瓨鐨勬暟鎹�
+     * @return 缂撳瓨鏁版嵁鐨勫璞�
+     */
+    public static <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
+        RSet<T> rSet = CLIENT.getSet(key);
+        return rSet.addAll(dataSet);
+    }
+
+    /**
+     * 娉ㄥ唽Set鐩戝惉鍣�
+     * <p>
+     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param listener 鐩戝惉鍣ㄩ厤缃�
+     */
+    public static <T> void addSetListener(final String key, final ObjectListener listener) {
+        RSet<T> rSet = CLIENT.getSet(key);
+        rSet.addListener(listener);
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨剆et
+     *
+     * @param key 缂撳瓨鐨刱ey
+     * @return set瀵硅薄
+     */
+    public static <T> Set<T> getCacheSet(final String key) {
+        RSet<T> rSet = CLIENT.getSet(key);
+        return rSet.readAll();
+    }
+
+    /**
+     * 缂撳瓨Map
+     *
+     * @param key     缂撳瓨鐨勯敭鍊�
+     * @param dataMap 缂撳瓨鐨勬暟鎹�
+     */
+    public static <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
+        if (dataMap != null) {
+            RMap<String, T> rMap = CLIENT.getMap(key);
+            rMap.putAll(dataMap);
+        }
+    }
+
+    /**
+     * 娉ㄥ唽Map鐩戝惉鍣�
+     * <p>
+     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param listener 鐩戝惉鍣ㄩ厤缃�
+     */
+    public static <T> void addMapListener(final String key, final ObjectListener listener) {
+        RMap<String, T> rMap = CLIENT.getMap(key);
+        rMap.addListener(listener);
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨凪ap
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return map瀵硅薄
+     */
+    public static <T> Map<String, T> getCacheMap(final String key) {
+        RMap<String, T> rMap = CLIENT.getMap(key);
+        return rMap.getAll(rMap.keySet());
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨Map鐨刱ey鍒楄〃
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return key鍒楄〃
+     */
+    public static <T> Set<String> getCacheMapKeySet(final String key) {
+        RMap<String, T> rMap = CLIENT.getMap(key);
+        return rMap.keySet();
+    }
+
+    /**
+     * 寰�Hash涓瓨鍏ユ暟鎹�
+     *
+     * @param key   Redis閿�
+     * @param hKey  Hash閿�
+     * @param value 鍊�
+     */
+    public static <T> void setCacheMapValue(final String key, final String hKey, final T value) {
+        RMap<String, T> rMap = CLIENT.getMap(key);
+        rMap.put(hKey, value);
+    }
+
+    /**
+     * 鑾峰彇Hash涓殑鏁版嵁
+     *
+     * @param key  Redis閿�
+     * @param hKey Hash閿�
+     * @return Hash涓殑瀵硅薄
+     */
+    public static <T> T getCacheMapValue(final String key, final String hKey) {
+        RMap<String, T> rMap = CLIENT.getMap(key);
+        return rMap.get(hKey);
+    }
+
+    /**
+     * 鍒犻櫎Hash涓殑鏁版嵁
+     *
+     * @param key  Redis閿�
+     * @param hKey Hash閿�
+     * @return Hash涓殑瀵硅薄
+     */
+    public static <T> T delCacheMapValue(final String key, final String hKey) {
+        RMap<String, T> rMap = CLIENT.getMap(key);
+        return rMap.remove(hKey);
+    }
+
+    /**
+     * 鑾峰彇澶氫釜Hash涓殑鏁版嵁
+     *
+     * @param key   Redis閿�
+     * @param hKeys Hash閿泦鍚�
+     * @return Hash瀵硅薄闆嗗悎
+     */
+    public static <K, V> Map<K, V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
+        RMap<K, V> rMap = CLIENT.getMap(key);
+        return rMap.getAll(hKeys);
+    }
+
+    /**
+     * 璁剧疆鍘熷瓙鍊�
+     *
+     * @param key   Redis閿�
+     * @param value 鍊�
+     */
+    public static void setAtomicValue(String key, long value) {
+        RAtomicLong atomic = CLIENT.getAtomicLong(key);
+        atomic.set(value);
+    }
+
+    /**
+     * 鑾峰彇鍘熷瓙鍊�
+     *
+     * @param key Redis閿�
+     * @return 褰撳墠鍊�
+     */
+    public static long getAtomicValue(String key) {
+        RAtomicLong atomic = CLIENT.getAtomicLong(key);
+        return atomic.get();
+    }
+
+    /**
+     * 閫掑鍘熷瓙鍊�
+     *
+     * @param key Redis閿�
+     * @return 褰撳墠鍊�
+     */
+    public static long incrAtomicValue(String key) {
+        RAtomicLong atomic = CLIENT.getAtomicLong(key);
+        return atomic.incrementAndGet();
+    }
+
+    /**
+     * 閫掑噺鍘熷瓙鍊�
+     *
+     * @param key Redis閿�
+     * @return 褰撳墠鍊�
+     */
+    public static long decrAtomicValue(String key) {
+        RAtomicLong atomic = CLIENT.getAtomicLong(key);
+        return atomic.decrementAndGet();
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞″垪琛�
+     *
+     * @param pattern 瀛楃涓插墠缂�
+     * @return 瀵硅薄鍒楄〃
+     */
+    public static Collection<String> keys(final String pattern) {
+        Stream<String> stream = CLIENT.getKeys().getKeysStreamByPattern(pattern);
+        return stream.collect(Collectors.toList());
+    }
+
+    /**
+     * 鍒犻櫎缂撳瓨鐨勫熀鏈璞″垪琛�
+     *
+     * @param pattern 瀛楃涓插墠缂�
+     */
+    public static void deleteKeys(final String pattern) {
+        CLIENT.getKeys().deleteByPattern(pattern);
+    }
+
+    /**
+     * 妫�鏌edis涓槸鍚﹀瓨鍦╧ey
+     *
+     * @param key 閿�
+     */
+    public static Boolean hasKey(String key) {
+        RKeys rKeys = CLIENT.getKeys();
+        return rKeys.countExists(key) > 0;
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..fe5d8b9
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.redis.config.RedisConfig
diff --git a/ruoyi-common/ruoyi-common-satoken/pom.xml b/ruoyi-common/ruoyi-common-satoken/pom.xml
new file mode 100644
index 0000000..0020d9f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/pom.xml
@@ -0,0 +1,39 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-satoken</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <!-- RuoYi Common Redis-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+
+        <!-- Sa-Token 鏉冮檺璁よ瘉, 鍦ㄧ嚎鏂囨。锛歨ttp://sa-token.dev33.cn/ -->
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-spring-boot3-starter</artifactId>
+        </dependency>
+        <!-- Sa-Token 鏁村悎 jwt -->
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-jwt</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfig.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfig.java
new file mode 100644
index 0000000..d1d5260
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/config/SaTokenConfig.java
@@ -0,0 +1,23 @@
+package com.ruoyi.common.satoken.config;
+
+import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
+import cn.dev33.satoken.stp.StpLogic;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * sa-token 閰嶇疆
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+public class SaTokenConfig implements WebMvcConfigurer {
+
+    @Bean
+    public StpLogic getStpLogicJwt() {
+        // Sa-Token 鏁村悎 jwt (绠�鍗曟ā寮�)
+        return new StpLogicJwtForSimple();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java
new file mode 100644
index 0000000..52dd903
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/dao/PlusSaTokenDao.java
@@ -0,0 +1,178 @@
+package com.ruoyi.common.satoken.core.dao;
+
+import cn.dev33.satoken.dao.SaTokenDao;
+import cn.dev33.satoken.util.SaFoxUtil;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import org.springframework.stereotype.Component;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Sa-Token鎸佷箙灞傛帴鍙�(浣跨敤妗嗘灦鑷甫RedisUtils瀹炵幇 鍗忚缁熶竴)
+ *
+ * @author Lion Li
+ */
+@Component
+public class PlusSaTokenDao implements SaTokenDao {
+
+    /**
+     * 鑾峰彇Value锛屽鏃犺繑绌�
+     */
+    @Override
+    public String get(String key) {
+        return RedisUtils.getCacheObject(key);
+    }
+
+    /**
+     * 鍐欏叆Value锛屽苟璁惧畾瀛樻椿鏃堕棿 (鍗曚綅: 绉�)
+     */
+    @Override
+    public void set(String key, String value, long timeout) {
+        if (timeout == 0 || timeout <= NOT_VALUE_EXPIRE) {
+            return;
+        }
+        // 鍒ゆ柇鏄惁涓烘案涓嶈繃鏈�
+        if (timeout == NEVER_EXPIRE) {
+            RedisUtils.setCacheObject(key, value);
+        } else {
+            RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout));
+        }
+    }
+
+    /**
+     * 淇慨鏀规寚瀹歬ey-value閿�煎 (杩囨湡鏃堕棿涓嶅彉)
+     */
+    @Override
+    public void update(String key, String value) {
+        long expire = getTimeout(key);
+        // -2 = 鏃犳閿�
+        if (expire == NOT_VALUE_EXPIRE) {
+            return;
+        }
+        this.set(key, value, expire);
+    }
+
+    /**
+     * 鍒犻櫎Value
+     */
+    @Override
+    public void delete(String key) {
+        RedisUtils.deleteObject(key);
+    }
+
+    /**
+     * 鑾峰彇Value鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
+     */
+    @Override
+    public long getTimeout(String key) {
+        long timeout = RedisUtils.getTimeToLive(key);
+        return timeout < 0 ? timeout : timeout / 1000;
+    }
+
+    /**
+     * 淇敼Value鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
+     */
+    @Override
+    public void updateTimeout(String key, long timeout) {
+        // 鍒ゆ柇鏄惁鎯宠璁剧疆涓烘案涔�
+        if (timeout == NEVER_EXPIRE) {
+            long expire = getTimeout(key);
+            if (expire == NEVER_EXPIRE) {
+                // 濡傛灉鍏跺凡缁忚璁剧疆涓烘案涔咃紝鍒欎笉浣滀换浣曞鐞�
+            } else {
+                // 濡傛灉灏氭湭琚缃负姘镐箙锛岄偅涔堝啀娆et涓�娆�
+                this.set(key, this.get(key), timeout);
+            }
+            return;
+        }
+        RedisUtils.expire(key, Duration.ofSeconds(timeout));
+    }
+
+
+    /**
+     * 鑾峰彇Object锛屽鏃犺繑绌�
+     */
+    @Override
+    public Object getObject(String key) {
+        return RedisUtils.getCacheObject(key);
+    }
+
+    /**
+     * 鍐欏叆Object锛屽苟璁惧畾瀛樻椿鏃堕棿 (鍗曚綅: 绉�)
+     */
+    @Override
+    public void setObject(String key, Object object, long timeout) {
+        if (timeout == 0 || timeout <= NOT_VALUE_EXPIRE) {
+            return;
+        }
+        // 鍒ゆ柇鏄惁涓烘案涓嶈繃鏈�
+        if (timeout == NEVER_EXPIRE) {
+            RedisUtils.setCacheObject(key, object);
+        } else {
+            RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout));
+        }
+    }
+
+    /**
+     * 鏇存柊Object (杩囨湡鏃堕棿涓嶅彉)
+     */
+    @Override
+    public void updateObject(String key, Object object) {
+        long expire = getObjectTimeout(key);
+        // -2 = 鏃犳閿�
+        if (expire == NOT_VALUE_EXPIRE) {
+            return;
+        }
+        this.setObject(key, object, expire);
+    }
+
+    /**
+     * 鍒犻櫎Object
+     */
+    @Override
+    public void deleteObject(String key) {
+        RedisUtils.deleteObject(key);
+    }
+
+    /**
+     * 鑾峰彇Object鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
+     */
+    @Override
+    public long getObjectTimeout(String key) {
+        long timeout = RedisUtils.getTimeToLive(key);
+        return timeout < 0 ? timeout : timeout / 1000;
+    }
+
+    /**
+     * 淇敼Object鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
+     */
+    @Override
+    public void updateObjectTimeout(String key, long timeout) {
+        // 鍒ゆ柇鏄惁鎯宠璁剧疆涓烘案涔�
+        if (timeout == NEVER_EXPIRE) {
+            long expire = getObjectTimeout(key);
+            if (expire == NEVER_EXPIRE) {
+                // 濡傛灉鍏跺凡缁忚璁剧疆涓烘案涔咃紝鍒欎笉浣滀换浣曞鐞�
+            } else {
+                // 濡傛灉灏氭湭琚缃负姘镐箙锛岄偅涔堝啀娆et涓�娆�
+                this.setObject(key, this.getObject(key), timeout);
+            }
+            return;
+        }
+        RedisUtils.expire(key, Duration.ofSeconds(timeout));
+    }
+
+
+    /**
+     * 鎼滅储鏁版嵁
+     */
+    @Override
+    public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType) {
+        Collection<String> keys = RedisUtils.keys(prefix + "*" + keyword + "*");
+        List<String> list = new ArrayList<>(keys);
+        return SaFoxUtil.searchList(list, start, size, sortType);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaPermissionImpl.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaPermissionImpl.java
new file mode 100644
index 0000000..c1f9a29
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/core/service/SaPermissionImpl.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.satoken.core.service;
+
+import cn.dev33.satoken.stp.StpInterface;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.enums.UserType;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * sa-token 鏉冮檺绠$悊瀹炵幇绫�
+ *
+ * @author Lion Li
+ */
+@Component
+public class SaPermissionImpl implements StpInterface {
+
+    /**
+     * 鑾峰彇鑿滃崟鏉冮檺鍒楄〃
+     */
+    @Override
+    public List<String> getPermissionList(Object loginId, String loginType) {
+        LoginUser loginUser = LoginHelper.getLoginUser();
+        UserType userType = UserType.getUserType(loginUser.getUserType());
+        if (userType == UserType.SYS_USER) {
+            return new ArrayList<>(loginUser.getMenuPermission());
+        } else if (userType == UserType.APP_USER) {
+            // 鍏朵粬绔� 鑷鏍规嵁涓氬姟缂栧啓
+        }
+        return new ArrayList<>();
+    }
+
+    /**
+     * 鑾峰彇瑙掕壊鏉冮檺鍒楄〃
+     */
+    @Override
+    public List<String> getRoleList(Object loginId, String loginType) {
+        LoginUser loginUser = LoginHelper.getLoginUser();
+        UserType userType = UserType.getUserType(loginUser.getUserType());
+        if (userType == UserType.SYS_USER) {
+            return new ArrayList<>(loginUser.getRolePermission());
+        } else if (userType == UserType.APP_USER) {
+            // 鍏朵粬绔� 鑷鏍规嵁涓氬姟缂栧啓
+        }
+        return new ArrayList<>();
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/listener/UserActionListener.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/listener/UserActionListener.java
new file mode 100644
index 0000000..e1070fb
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/listener/UserActionListener.java
@@ -0,0 +1,139 @@
+package com.ruoyi.common.satoken.listener;
+
+import cn.dev33.satoken.config.SaTokenConfig;
+import cn.dev33.satoken.listener.SaTokenListener;
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.hutool.http.useragent.UserAgent;
+import cn.hutool.http.useragent.UserAgentUtil;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.enums.UserType;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.ip.AddressUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.time.Duration;
+
+/**
+ * 鐢ㄦ埛琛屼负 渚﹀惉鍣ㄧ殑瀹炵幇
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Component
+@Slf4j
+public class UserActionListener implements SaTokenListener {
+
+    private final SaTokenConfig tokenConfig;
+
+    /**
+     * 姣忔鐧诲綍鏃惰Е鍙�
+     */
+    @Override
+    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
+        UserType userType = UserType.getUserType(loginId.toString());
+        if (userType == UserType.SYS_USER) {
+            UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
+            String ip = ServletUtils.getClientIP();
+            LoginUser user = LoginHelper.getLoginUser();
+            UserOnlineDTO dto = new UserOnlineDTO();
+            dto.setIpaddr(ip);
+            dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+            dto.setBrowser(userAgent.getBrowser().getName());
+            dto.setOs(userAgent.getOs().getName());
+            dto.setLoginTime(System.currentTimeMillis());
+            dto.setTokenId(tokenValue);
+            dto.setUserName(user.getUsername());
+            dto.setDeptName(user.getDeptName());
+            if(tokenConfig.getTimeout() == -1) {
+                RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto);
+            } else {
+                RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout()));
+            }
+            log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
+        } else if (userType == UserType.APP_USER) {
+            // app绔� 鑷鏍规嵁涓氬姟缂栧啓
+        }
+    }
+
+    /**
+     * 姣忔娉ㄩ攢鏃惰Е鍙�
+     */
+    @Override
+    public void doLogout(String loginType, Object loginId, String tokenValue) {
+        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
+        log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue);
+    }
+
+    /**
+     * 姣忔琚涪涓嬬嚎鏃惰Е鍙�
+     */
+    @Override
+    public void doKickout(String loginType, Object loginId, String tokenValue) {
+        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
+        log.info("user doLogoutByLoginId, userId:{}, token:{}", loginId, tokenValue);
+    }
+
+    /**
+     * 姣忔琚《涓嬬嚎鏃惰Е鍙�
+     */
+    @Override
+    public void doReplaced(String loginType, Object loginId, String tokenValue) {
+        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
+        log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue);
+    }
+
+    /**
+     * 姣忔琚皝绂佹椂瑙﹀彂
+     */
+    @Override
+    public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
+    }
+
+    /**
+     * 姣忔琚В灏佹椂瑙﹀彂
+     */
+    @Override
+    public void doUntieDisable(String loginType, Object loginId, String service) {
+    }
+
+    /**
+     * 姣忔鎵撳紑浜岀骇璁よ瘉鏃惰Е鍙�
+     */
+    @Override
+    public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
+    }
+
+    /**
+     * 姣忔鍒涘缓Session鏃惰Е鍙�
+     */
+    @Override
+    public void doCloseSafe(String loginType, String tokenValue, String service) {
+    }
+
+    /**
+     * 姣忔鍒涘缓Session鏃惰Е鍙�
+     */
+    @Override
+    public void doCreateSession(String id) {
+    }
+
+    /**
+     * 姣忔娉ㄩ攢Session鏃惰Е鍙�
+     */
+    @Override
+    public void doLogoutSession(String id) {
+    }
+
+    /**
+     * 姣忔Token缁湡鏃惰Е鍙�
+     */
+    @Override
+    public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java
new file mode 100644
index 0000000..0ae9016
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/com/ruoyi/common/satoken/utils/LoginHelper.java
@@ -0,0 +1,135 @@
+package com.ruoyi.common.satoken.utils;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.enums.DeviceType;
+import com.ruoyi.common.core.enums.UserType;
+import com.ruoyi.common.core.exception.UtilException;
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * 鐧诲綍閴存潈鍔╂墜
+ *
+ * user_type 涓� 鐢ㄦ埛绫诲瀷 鍚屼竴涓敤鎴疯〃 鍙互鏈夊绉嶇敤鎴风被鍨� 渚嬪 pc,app
+ * deivce 涓� 璁惧绫诲瀷 鍚屼竴涓敤鎴风被鍨� 鍙互鏈� 澶氱璁惧绫诲瀷 渚嬪 web,ios
+ * 鍙互缁勬垚 鐢ㄦ埛绫诲瀷涓庤澶囩被鍨嬪瀵瑰鐨� 鏉冮檺鐏垫椿鎺у埗
+ *
+ * 澶氱敤鎴蜂綋绯� 閽堝 澶氱鐢ㄦ埛绫诲瀷 浣嗘潈闄愭帶鍒朵笉涓�鑷�
+ * 鍙互缁勬垚 澶氱敤鎴风被鍨嬭〃涓庡璁惧绫诲瀷 鍒嗗埆鎺у埗鏉冮檺
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class LoginHelper {
+
+    public static final String JOIN_CODE = ":";
+    public static final String LOGIN_USER_KEY = "loginUser";
+
+    /**
+     * 鐧诲綍绯荤粺
+     *
+     * @param loginUser 鐧诲綍鐢ㄦ埛淇℃伅
+     */
+    public static void login(LoginUser loginUser) {
+        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
+        StpUtil.login(loginUser.getLoginId());
+        setLoginUser(loginUser);
+    }
+
+    /**
+     * 鐧诲綍绯荤粺 鍩轰簬 璁惧绫诲瀷
+     * 閽堝鐩稿悓鐢ㄦ埛浣撶郴涓嶅悓璁惧
+     *
+     * @param loginUser 鐧诲綍鐢ㄦ埛淇℃伅
+     */
+    public static void loginByDevice(LoginUser loginUser, DeviceType deviceType) {
+        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
+        StpUtil.login(loginUser.getLoginId(), deviceType.getDevice());
+        setLoginUser(loginUser);
+    }
+
+    /**
+     * 璁剧疆鐢ㄦ埛鏁版嵁(澶氱骇缂撳瓨)
+     */
+    public static void setLoginUser(LoginUser loginUser) {
+        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛(澶氱骇缂撳瓨)
+     */
+    public static LoginUser getLoginUser() {
+        LoginUser loginUser = (LoginUser) SaHolder.getStorage().get(LOGIN_USER_KEY);
+        if (loginUser != null) {
+            return loginUser;
+        }
+        loginUser = (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
+        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
+        return loginUser;
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛id
+     */
+    public static Long getUserId() {
+        LoginUser loginUser = getLoginUser();
+        if (ObjectUtil.isNull(loginUser)) {
+            String loginId = StpUtil.getLoginIdAsString();
+            String userId = null;
+            for (UserType value : UserType.values()) {
+                if (StringUtils.contains(loginId, value.getUserType())) {
+                    String[] strs = StringUtils.split(loginId, JOIN_CODE);
+                    // 鐢ㄦ埛id鍦ㄦ�绘槸鍦ㄦ渶鍚�
+                    userId = strs[strs.length - 1];
+                }
+            }
+            if (StringUtils.isBlank(userId)) {
+                throw new UtilException("鐧诲綍鐢ㄦ埛: LoginId寮傚父 => " + loginId);
+            }
+            return Long.parseLong(userId);
+        }
+        return loginUser.getUserId();
+    }
+
+    /**
+     * 鑾峰彇閮ㄩ棬ID
+     */
+    public static Long getDeptId() {
+        return getLoginUser().getDeptId();
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛璐︽埛
+     */
+    public static String getUsername() {
+        return getLoginUser().getUsername();
+    }
+
+    /**
+     * 鑾峰彇鐢ㄦ埛绫诲瀷
+     */
+    public static UserType getUserType() {
+        String loginId = StpUtil.getLoginIdAsString();
+        return UserType.getUserType(loginId);
+    }
+
+    /**
+     * 鏄惁涓虹鐞嗗憳
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    public static boolean isAdmin(Long userId) {
+        return UserConstants.ADMIN_ID.equals(userId);
+    }
+
+    public static boolean isAdmin() {
+        return isAdmin(getUserId());
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..fd02ac5
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+com.ruoyi.common.satoken.core.dao.PlusSaTokenDao
+com.ruoyi.common.satoken.core.service.SaPermissionImpl
diff --git a/ruoyi-common/ruoyi-common-security/pom.xml b/ruoyi-common/ruoyi-common-security/pom.xml
new file mode 100644
index 0000000..eaa3258
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-security/pom.xml
@@ -0,0 +1,33 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-security</artifactId>
+
+    <description>
+        ruoyi-common-security 瀹夊叏妯″潡
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-satoken</artifactId>
+        </dependency>
+
+        <!-- Sa-Token 鏉冮檺璁よ瘉, 鍦ㄧ嚎鏂囨。锛歨ttp://sa-token.dev33.cn/ -->
+        <dependency>
+            <groupId>cn.dev33</groupId>
+            <artifactId>sa-token-spring-boot3-starter</artifactId>
+            <version>${satoken.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java
new file mode 100644
index 0000000..6a6bbbe
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java
@@ -0,0 +1,53 @@
+package com.ruoyi.common.security.config;
+
+import cn.dev33.satoken.interceptor.SaInterceptor;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.stp.StpUtil;
+import com.ruoyi.common.security.config.properties.SecurityProperties;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * 鏉冮檺瀹夊叏閰嶇疆
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Slf4j
+@AutoConfiguration
+public class SecurityConfig implements WebMvcConfigurer {
+
+    private final SecurityProperties securityProperties;
+
+    /**
+     * 娉ㄥ唽sa-token鐨勬嫤鎴櫒
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 娉ㄥ唽璺敱鎷︽埅鍣紝鑷畾涔夐獙璇佽鍒�
+        registry.addInterceptor(new SaInterceptor(handler -> {
+            // 鐧诲綍楠岃瘉 -- 鎺掗櫎澶氫釜璺緞
+            SaRouter
+                // 鑾峰彇鎵�鏈夌殑
+                .match("/**")
+                // 瀵规湭鎺掗櫎鐨勮矾寰勮繘琛屾鏌�
+                .check(() -> {
+                    // 妫�鏌ユ槸鍚︾櫥褰� 鏄惁鏈塼oken
+                    StpUtil.checkLogin();
+
+                    // 鏈夋晥鐜囧奖鍝� 鐢ㄤ簬涓存椂娴嬭瘯
+                    // if (log.isDebugEnabled()) {
+                    //     log.debug("鍓╀綑鏈夋晥鏃堕棿: {}", StpUtil.getTokenTimeout());
+                    //     log.debug("涓存椂鏈夋晥鏃堕棿: {}", StpUtil.getTokenActivityTimeout());
+                    // }
+
+                });
+        })).addPathPatterns("/**")
+            // 鎺掗櫎涓嶉渶瑕佹嫤鎴殑璺緞
+            .excludePathPatterns(securityProperties.getExcludes());
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/properties/SecurityProperties.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/properties/SecurityProperties.java
new file mode 100644
index 0000000..938ab94
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/properties/SecurityProperties.java
@@ -0,0 +1,23 @@
+package com.ruoyi.common.security.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * Security 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "security")
+public class SecurityProperties {
+
+    /**
+     * 鎺掗櫎璺緞
+     */
+    private String[] excludes;
+
+
+}
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..f8f0041
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java
@@ -0,0 +1,141 @@
+package com.ruoyi.common.security.handler;
+
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.exception.NotPermissionException;
+import cn.dev33.satoken.exception.NotRoleException;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpStatus;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.exception.DemoModeException;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StreamUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.support.DefaultMessageSourceResolvable;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+
+/**
+ * 鍏ㄥ眬寮傚父澶勭悊鍣�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    /**
+     * 鏉冮檺鐮佸紓甯�
+     */
+    @ExceptionHandler(NotPermissionException.class)
+    public R<Void> handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鏉冮檺鐮佹牎楠屽け璐�'{}'", requestURI, e.getMessage());
+        return R.fail(HttpStatus.HTTP_FORBIDDEN, "娌℃湁璁块棶鏉冮檺锛岃鑱旂郴绠$悊鍛樻巿鏉�");
+    }
+
+    /**
+     * 瑙掕壊鏉冮檺寮傚父
+     */
+    @ExceptionHandler(NotRoleException.class)
+    public R<Void> handleNotRoleException(NotRoleException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',瑙掕壊鏉冮檺鏍¢獙澶辫触'{}'", requestURI, e.getMessage());
+        return R.fail(HttpStatus.HTTP_FORBIDDEN, "娌℃湁璁块棶鏉冮檺锛岃鑱旂郴绠$悊鍛樻巿鏉�");
+    }
+
+    /**
+     * 璁よ瘉澶辫触
+     */
+    @ExceptionHandler(NotLoginException.class)
+    public R<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',璁よ瘉澶辫触'{}',鏃犳硶璁块棶绯荤粺璧勬簮", requestURI, e.getMessage());
+        return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "璁よ瘉澶辫触锛屾棤娉曡闂郴缁熻祫婧�");
+    }
+
+    /**
+     * 璇锋眰鏂瑰紡涓嶆敮鎸�
+     */
+    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+    public R<Void> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
+                                                                HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',涓嶆敮鎸�'{}'璇锋眰", requestURI, e.getMethod());
+        return R.fail(e.getMessage());
+    }
+
+    /**
+     * 涓氬姟寮傚父
+     */
+    @ExceptionHandler(ServiceException.class)
+    public R<Void> handleServiceException(ServiceException e, HttpServletRequest request) {
+        log.error(e.getMessage(), e);
+        Integer code = e.getCode();
+        return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
+    }
+
+    /**
+     * 鎷︽埅鏈煡鐨勮繍琛屾椂寮傚父
+     */
+    @ExceptionHandler(RuntimeException.class)
+    public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鍙戠敓鏈煡寮傚父.", requestURI, e);
+        return R.fail(e.getMessage());
+    }
+
+    /**
+     * 绯荤粺寮傚父
+     */
+    @ExceptionHandler(Exception.class)
+    public R<Void> handleException(Exception e, HttpServletRequest request) {
+        String requestURI = request.getRequestURI();
+        log.error("璇锋眰鍦板潃'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+        return R.fail(e.getMessage());
+    }
+
+    /**
+     * 鑷畾涔夐獙璇佸紓甯�
+     */
+    @ExceptionHandler(BindException.class)
+    public R<Void> handleBindException(BindException e) {
+        log.error(e.getMessage(), e);
+        String message = StreamUtils.join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", ");
+        return R.fail(message);
+    }
+
+    /**
+     * 鑷畾涔夐獙璇佸紓甯�
+     */
+    @ExceptionHandler(ConstraintViolationException.class)
+    public R<Void> constraintViolationException(ConstraintViolationException e) {
+        log.error(e.getMessage(), e);
+        String message = StreamUtils.join(e.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
+        return R.fail(message);
+    }
+
+    /**
+     * 鑷畾涔夐獙璇佸紓甯�
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
+        log.error(e.getMessage(), e);
+        String message = e.getBindingResult().getFieldError().getDefaultMessage();
+        return R.fail(message);
+    }
+
+    /**
+     * 婕旂ず妯″紡寮傚父
+     */
+    @ExceptionHandler(DemoModeException.class)
+    public R<Void> handleDemoModeException(DemoModeException e) {
+        return R.fail("婕旂ず妯″紡锛屼笉鍏佽鎿嶄綔");
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..a09e5d6
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,2 @@
+com.ruoyi.common.security.handler.GlobalExceptionHandler
+com.ruoyi.common.security.config.SecurityConfig
diff --git a/ruoyi-common/ruoyi-common-sms/pom.xml b/ruoyi-common/ruoyi-common-sms/pom.xml
new file mode 100644
index 0000000..0ea416d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/pom.xml
@@ -0,0 +1,37 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-sms</artifactId>
+
+    <description>
+        ruoyi-common-sms 鐭俊妯″潡
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dysmsapi20170525</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java-sms</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/SmsConfig.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/SmsConfig.java
new file mode 100644
index 0000000..ecc89af
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/SmsConfig.java
@@ -0,0 +1,48 @@
+package com.ruoyi.common.sms.config;
+
+import com.ruoyi.common.sms.config.properties.SmsProperties;
+import com.ruoyi.common.sms.core.AliyunSmsTemplate;
+import com.ruoyi.common.sms.core.SmsTemplate;
+import com.ruoyi.common.sms.core.TencentSmsTemplate;
+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.Configuration;
+
+/**
+ * 鐭俊閰嶇疆绫�
+ *
+ * @author Lion Li
+ * @version 4.2.0
+ */
+@AutoConfiguration
+@EnableConfigurationProperties(SmsProperties.class)
+public class SmsConfig {
+
+    @Configuration
+    @ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
+    @ConditionalOnClass(com.aliyun.dysmsapi20170525.Client.class)
+    static class AliyunSmsConfig {
+
+        @Bean
+        public SmsTemplate aliyunSmsTemplate(SmsProperties smsProperties) {
+            return new AliyunSmsTemplate(smsProperties);
+        }
+
+    }
+
+    @Configuration
+    @ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
+    @ConditionalOnClass(com.tencentcloudapi.sms.v20190711.SmsClient.class)
+    static class TencentSmsConfig {
+
+        @Bean
+        public SmsTemplate tencentSmsTemplate(SmsProperties smsProperties) {
+            return new TencentSmsTemplate(smsProperties);
+        }
+
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/properties/SmsProperties.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/properties/SmsProperties.java
new file mode 100644
index 0000000..5562178
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/config/properties/SmsProperties.java
@@ -0,0 +1,47 @@
+package com.ruoyi.common.sms.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * SMS鐭俊 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ * @version 4.2.0
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "sms")
+public class SmsProperties {
+
+    private Boolean enabled;
+
+    /**
+     * 閰嶇疆鑺傜偣
+     * 闃块噷浜� dysmsapi.aliyuncs.com
+     * 鑵捐浜� sms.tencentcloudapi.com
+     */
+    private String endpoint;
+
+    /**
+     * key
+     */
+    private String accessKeyId;
+
+    /**
+     * 瀵嗗寵
+     */
+    private String accessKeySecret;
+
+    /*
+     * 鐭俊绛惧悕
+     */
+    private String signName;
+
+    /**
+     * 鐭俊搴旂敤ID (鑵捐涓撳睘)
+     */
+    private String sdkAppId;
+
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/AliyunSmsTemplate.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/AliyunSmsTemplate.java
new file mode 100644
index 0000000..28f67d2
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/AliyunSmsTemplate.java
@@ -0,0 +1,66 @@
+package com.ruoyi.common.sms.core;
+
+import com.aliyun.dysmsapi20170525.Client;
+import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
+import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
+import com.aliyun.teaopenapi.models.Config;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.sms.config.properties.SmsProperties;
+import com.ruoyi.common.sms.entity.SmsResult;
+import com.ruoyi.common.sms.exception.SmsException;
+import lombok.SneakyThrows;
+
+import java.util.Map;
+
+/**
+ * Aliyun 鐭俊妯℃澘
+ *
+ * @author Lion Li
+ * @version 4.2.0
+ */
+public class AliyunSmsTemplate implements SmsTemplate {
+
+    private SmsProperties properties;
+
+    private Client client;
+
+    @SneakyThrows(Exception.class)
+    public AliyunSmsTemplate(SmsProperties smsProperties) {
+        this.properties = smsProperties;
+        Config config = new Config()
+            // 鎮ㄧ殑AccessKey ID
+            .setAccessKeyId(smsProperties.getAccessKeyId())
+            // 鎮ㄧ殑AccessKey Secret
+            .setAccessKeySecret(smsProperties.getAccessKeySecret())
+            // 璁块棶鐨勫煙鍚�
+            .setEndpoint(smsProperties.getEndpoint());
+        this.client = new Client(config);
+    }
+
+    @Override
+    public SmsResult send(String phones, String templateId, Map<String, String> param) {
+        if (StringUtils.isBlank(phones)) {
+            throw new SmsException("鎵嬫満鍙蜂笉鑳戒负绌�");
+        }
+        if (StringUtils.isBlank(templateId)) {
+            throw new SmsException("妯℃澘ID涓嶈兘涓虹┖");
+        }
+        SendSmsRequest req = new SendSmsRequest()
+            .setPhoneNumbers(phones)
+            .setSignName(properties.getSignName())
+            .setTemplateCode(templateId)
+            .setTemplateParam(JsonUtils.toJsonString(param));
+        try {
+            SendSmsResponse resp = client.sendSms(req);
+            return SmsResult.builder()
+                .isSuccess("OK".equals(resp.getBody().getCode()))
+                .message(resp.getBody().getMessage())
+                .response(JsonUtils.toJsonString(resp))
+                .build();
+        } catch (Exception e) {
+            throw new SmsException(e.getMessage());
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/SmsTemplate.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/SmsTemplate.java
new file mode 100644
index 0000000..eb61b86
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/SmsTemplate.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.sms.core;
+
+import com.ruoyi.common.sms.entity.SmsResult;
+
+import java.util.Map;
+
+/**
+ * 鐭俊妯℃澘
+ *
+ * @author Lion Li
+ * @version 4.2.0
+ */
+public interface SmsTemplate {
+
+    /**
+     * 鍙戦�佺煭淇�
+     *
+     * @param phones     鐢佃瘽鍙�(澶氫釜閫楀彿鍒嗗壊)
+     * @param templateId 妯℃澘id
+     * @param param      妯℃澘瀵瑰簲鍙傛暟
+     *                   闃块噷 闇�浣跨敤 妯℃澘鍙橀噺鍚嶇О瀵瑰簲鍐呭 渚嬪: code=1234
+     *                   鑵捐 闇�浣跨敤 妯℃澘鍙橀噺椤哄簭瀵瑰簲鍐呭 渚嬪: 1=1234, 1涓烘ā鏉垮唴绗竴涓弬鏁�
+     */
+    SmsResult send(String phones, String templateId, Map<String, String> param);
+
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/TencentSmsTemplate.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/TencentSmsTemplate.java
new file mode 100644
index 0000000..8c45a02
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/core/TencentSmsTemplate.java
@@ -0,0 +1,82 @@
+package com.ruoyi.common.sms.core;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.sms.config.properties.SmsProperties;
+import com.ruoyi.common.sms.entity.SmsResult;
+import com.ruoyi.common.sms.exception.SmsException;
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.profile.ClientProfile;
+import com.tencentcloudapi.common.profile.HttpProfile;
+import com.tencentcloudapi.sms.v20190711.SmsClient;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
+import com.tencentcloudapi.sms.v20190711.models.SendStatus;
+import lombok.SneakyThrows;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tencent 鐭俊妯℃澘
+ *
+ * @author Lion Li
+ * @version 4.2.0
+ */
+public class TencentSmsTemplate implements SmsTemplate {
+
+    private SmsProperties properties;
+
+    private SmsClient client;
+
+    @SneakyThrows(Exception.class)
+    public TencentSmsTemplate(SmsProperties smsProperties) {
+        this.properties = smsProperties;
+        Credential credential = new Credential(smsProperties.getAccessKeyId(), smsProperties.getAccessKeySecret());
+        HttpProfile httpProfile = new HttpProfile();
+        httpProfile.setEndpoint(smsProperties.getEndpoint());
+        ClientProfile clientProfile = new ClientProfile();
+        clientProfile.setHttpProfile(httpProfile);
+        this.client = new SmsClient(credential, "", clientProfile);
+    }
+
+    @Override
+    public SmsResult send(String phones, String templateId, Map<String, String> param) {
+        if (StringUtils.isBlank(phones)) {
+            throw new SmsException("鎵嬫満鍙蜂笉鑳戒负绌�");
+        }
+        if (StringUtils.isBlank(templateId)) {
+            throw new SmsException("妯℃澘ID涓嶈兘涓虹┖");
+        }
+        SendSmsRequest req = new SendSmsRequest();
+        Set<String> set = Arrays.stream(phones.split(",")).map(p -> "+86" + p).collect(Collectors.toSet());
+        req.setPhoneNumberSet(ArrayUtil.toArray(set, String.class));
+        if (CollUtil.isNotEmpty(param)) {
+            req.setTemplateParamSet(ArrayUtil.toArray(param.values(), String.class));
+        }
+        req.setTemplateID(templateId);
+        req.setSign(properties.getSignName());
+        req.setSmsSdkAppid(properties.getSdkAppId());
+        try {
+            SendSmsResponse resp = client.SendSms(req);
+            SmsResult.SmsResultBuilder builder = SmsResult.builder()
+                .isSuccess(true)
+                .message("send success")
+                .response(JsonUtils.toJsonString(resp));
+            for (SendStatus sendStatus : resp.getSendStatusSet()) {
+                if (!"Ok".equals(sendStatus.getCode())) {
+                    builder.isSuccess(false).message(sendStatus.getMessage());
+                    break;
+                }
+            }
+            return builder.build();
+        } catch (Exception e) {
+            throw new SmsException(e.getMessage());
+        }
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/entity/SmsResult.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/entity/SmsResult.java
new file mode 100644
index 0000000..d436805
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/entity/SmsResult.java
@@ -0,0 +1,31 @@
+package com.ruoyi.common.sms.entity;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 涓婁紶杩斿洖浣�
+ *
+ * @author Lion Li
+ */
+@Data
+@Builder
+public class SmsResult {
+
+    /**
+     * 鏄惁鎴愬姛
+     */
+    private boolean isSuccess;
+
+    /**
+     * 鍝嶅簲娑堟伅
+     */
+    private String message;
+
+    /**
+     * 瀹為檯鍝嶅簲浣�
+     * <p>
+     * 鍙嚜琛岃浆鎹负 SDK 瀵瑰簲鐨� SendSmsResponse
+     */
+    private String response;
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/exception/SmsException.java b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/exception/SmsException.java
new file mode 100644
index 0000000..a332aee
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/java/com/ruoyi/common/sms/exception/SmsException.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.sms.exception;
+
+import java.io.Serial;
+
+/**
+ * Sms寮傚父绫�
+ *
+ * @author Lion Li
+ */
+public class SmsException extends RuntimeException {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public SmsException(String msg) {
+        super(msg);
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..2eaa249
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.sms.config.SmsConfig
diff --git a/ruoyi-common/ruoyi-common-web/pom.xml b/ruoyi-common/ruoyi-common-web/pom.xml
new file mode 100644
index 0000000..30b9703
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/pom.xml
@@ -0,0 +1,58 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-web</artifactId>
+
+    <description>
+        ruoyi-common-web web鏈嶅姟
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+
+        <!-- SpringBoot Web瀹瑰櫒 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                    <groupId>org.springframework.boot</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- web 瀹瑰櫒浣跨敤 undertow 鎬ц兘鏇村己 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-crypto</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>transmittable-thread-local</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/CaptchaConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/CaptchaConfig.java
new file mode 100644
index 0000000..071550b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/CaptchaConfig.java
@@ -0,0 +1,62 @@
+package com.ruoyi.common.web.config;
+
+import cn.hutool.captcha.CaptchaUtil;
+import cn.hutool.captcha.CircleCaptcha;
+import cn.hutool.captcha.LineCaptcha;
+import cn.hutool.captcha.ShearCaptcha;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Lazy;
+
+import java.awt.*;
+
+/**
+ * 楠岃瘉鐮侀厤缃�
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+public class CaptchaConfig {
+
+    private static final int WIDTH = 160;
+    private static final int HEIGHT = 60;
+    private static final Color BACKGROUND = Color.PINK;
+    private static final Font FONT = new Font("Arial", Font.BOLD, 48);
+
+    /**
+     * 鍦嗗湀骞叉壈楠岃瘉鐮�
+     */
+    @Lazy
+    @Bean
+    public CircleCaptcha circleCaptcha() {
+        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(WIDTH, HEIGHT);
+        captcha.setBackground(BACKGROUND);
+        captcha.setFont(FONT);
+        return captcha;
+    }
+
+    /**
+     * 绾挎骞叉壈鐨勯獙璇佺爜
+     */
+    @Lazy
+    @Bean
+    public LineCaptcha lineCaptcha() {
+        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(WIDTH, HEIGHT);
+        captcha.setBackground(BACKGROUND);
+        captcha.setFont(FONT);
+        return captcha;
+    }
+
+    /**
+     * 鎵洸骞叉壈楠岃瘉鐮�
+     */
+    @Lazy
+    @Bean
+    public ShearCaptcha shearCaptcha() {
+        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(WIDTH, HEIGHT);
+        captcha.setBackground(BACKGROUND);
+        captcha.setFont(FONT);
+        return captcha;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/FilterConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/FilterConfig.java
new file mode 100644
index 0000000..a11ec79
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/FilterConfig.java
@@ -0,0 +1,55 @@
+package com.ruoyi.common.web.config;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.web.config.properties.XssProperties;
+import com.ruoyi.common.web.filter.RepeatableFilter;
+import com.ruoyi.common.web.filter.XssFilter;
+import org.springframework.beans.factory.annotation.Autowired;
+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 jakarta.servlet.DispatcherType;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Filter閰嶇疆
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+public class FilterConfig {
+
+    @Autowired
+    private XssProperties xssProperties;
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Bean
+    @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
+    public FilterRegistrationBean xssFilterRegistration() {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setDispatcherTypes(DispatcherType.REQUEST);
+        registration.setFilter(new XssFilter());
+        registration.addUrlPatterns(StringUtils.split(xssProperties.getUrlPatterns(), ","));
+        registration.setName("xssFilter");
+        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
+        Map<String, String> initParameters = new HashMap<String, String>();
+        initParameters.put("excludes", xssProperties.getExcludes());
+        registration.setInitParameters(initParameters);
+        return registration;
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Bean
+    public FilterRegistrationBean someFilterRegistration() {
+        FilterRegistrationBean registration = new FilterRegistrationBean();
+        registration.setFilter(new RepeatableFilter());
+        registration.addUrlPatterns("/*");
+        registration.setName("repeatableFilter");
+        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
+        return registration;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java
new file mode 100644
index 0000000..dd76619
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/I18nConfig.java
@@ -0,0 +1,22 @@
+package com.ruoyi.common.web.config;
+
+import com.ruoyi.common.web.core.I18nLocaleResolver;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.servlet.LocaleResolver;
+
+/**
+ * 鍥介檯鍖栭厤缃�
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration(before = WebMvcAutoConfiguration.class)
+public class I18nConfig {
+
+    @Bean
+    public LocaleResolver localeResolver() {
+        return new I18nLocaleResolver();
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/ResourcesConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/ResourcesConfig.java
new file mode 100644
index 0000000..a35ddb3
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/ResourcesConfig.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.web.config;
+
+import com.ruoyi.common.web.interceptor.PlusWebInvokeTimeInterceptor;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+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.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * 閫氱敤閰嶇疆
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+public class ResourcesConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        // 鍏ㄥ眬璁块棶鎬ц兘鎷︽埅
+        registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+    }
+
+    /**
+     * 璺ㄥ煙閰嶇疆
+     */
+    @Bean
+    public CorsFilter corsFilter() {
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        // 璁剧疆璁块棶婧愬湴鍧�
+        config.addAllowedOriginPattern("*");
+        // 璁剧疆璁块棶婧愯姹傚ご
+        config.addAllowedHeader("*");
+        // 璁剧疆璁块棶婧愯姹傛柟娉�
+        config.addAllowedMethod("*");
+        // 鏈夋晥鏈� 1800绉�
+        config.setMaxAge(1800L);
+        // 娣诲姞鏄犲皠璺緞锛屾嫤鎴竴鍒囪姹�
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", config);
+        // 杩斿洖鏂扮殑CorsFilter
+        return new CorsFilter(source);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/UndertowConfig.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/UndertowConfig.java
new file mode 100644
index 0000000..6659c3c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/UndertowConfig.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.web.config;
+
+import io.undertow.server.DefaultByteBufferPool;
+import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+
+/**
+ * Undertow 鑷畾涔夐厤缃�
+ *
+ * @author Lion Li
+ */
+@AutoConfiguration
+public class UndertowConfig implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
+
+    /**
+     * 璁剧疆 Undertow 鐨� websocket 缂撳啿姹�
+     */
+    @Override
+    public void customize(UndertowServletWebServerFactory factory) {
+        // 榛樿涓嶇洿鎺ュ垎閰嶅唴瀛� 濡傛灉椤圭洰涓娇鐢ㄤ簡 websocket 寤鸿鐩存帴鍒嗛厤
+        factory.addDeploymentInfoCustomizers(deploymentInfo -> {
+            WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
+            webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 512));
+            deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
+        });
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/CaptchaProperties.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/CaptchaProperties.java
new file mode 100644
index 0000000..9821fdf
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/CaptchaProperties.java
@@ -0,0 +1,38 @@
+package com.ruoyi.common.web.config.properties;
+
+import com.ruoyi.common.web.enums.CaptchaCategory;
+import com.ruoyi.common.web.enums.CaptchaType;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 楠岃瘉鐮� 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "captcha")
+public class CaptchaProperties {
+
+    /**
+     * 楠岃瘉鐮佺被鍨�
+     */
+    private CaptchaType type;
+
+    /**
+     * 楠岃瘉鐮佺被鍒�
+     */
+    private CaptchaCategory category;
+
+    /**
+     * 鏁板瓧楠岃瘉鐮佷綅鏁�
+     */
+    private Integer numberLength;
+
+    /**
+     * 瀛楃楠岃瘉鐮侀暱搴�
+     */
+    private Integer charLength;
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/XssProperties.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/XssProperties.java
new file mode 100644
index 0000000..83312f8
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/config/properties/XssProperties.java
@@ -0,0 +1,32 @@
+package com.ruoyi.common.web.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * xss杩囨护 閰嶇疆灞炴��
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "xss")
+public class XssProperties {
+
+    /**
+     * 杩囨护寮�鍏�
+     */
+    private String enabled;
+
+    /**
+     * 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+     */
+    private String excludes;
+
+    /**
+     * 鍖归厤閾炬帴
+     */
+    private String urlPatterns;
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java
new file mode 100644
index 0000000..6b741de
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/core/I18nLocaleResolver.java
@@ -0,0 +1,31 @@
+package com.ruoyi.common.web.core;
+
+import org.springframework.web.servlet.LocaleResolver;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.Locale;
+
+/**
+ * 鑾峰彇璇锋眰澶村浗闄呭寲淇℃伅
+ *
+ * @author Lion Li
+ */
+public class I18nLocaleResolver implements LocaleResolver {
+
+    @Override
+    public Locale resolveLocale(HttpServletRequest httpServletRequest) {
+        String language = httpServletRequest.getHeader("content-language");
+        Locale locale = Locale.getDefault();
+        if (language != null && language.length() > 0) {
+            String[] split = language.split("_");
+            locale = new Locale(split[0], split[1]);
+        }
+        return locale;
+    }
+
+    @Override
+    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
+
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaCategory.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaCategory.java
new file mode 100644
index 0000000..7fca5c2
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaCategory.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.web.enums;
+
+import cn.hutool.captcha.AbstractCaptcha;
+import cn.hutool.captcha.CircleCaptcha;
+import cn.hutool.captcha.LineCaptcha;
+import cn.hutool.captcha.ShearCaptcha;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 楠岃瘉鐮佺被鍒�
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum CaptchaCategory {
+
+    /**
+     * 绾挎骞叉壈
+     */
+    LINE(LineCaptcha.class),
+
+    /**
+     * 鍦嗗湀骞叉壈
+     */
+    CIRCLE(CircleCaptcha.class),
+
+    /**
+     * 鎵洸骞叉壈
+     */
+    SHEAR(ShearCaptcha.class);
+
+    private final Class<? extends AbstractCaptcha> clazz;
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaType.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaType.java
new file mode 100644
index 0000000..f78d572
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/enums/CaptchaType.java
@@ -0,0 +1,29 @@
+package com.ruoyi.common.web.enums;
+
+import cn.hutool.captcha.generator.CodeGenerator;
+import cn.hutool.captcha.generator.RandomGenerator;
+import com.ruoyi.common.web.utils.UnsignedMathGenerator;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 楠岃瘉鐮佺被鍨�
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum CaptchaType {
+
+    /**
+     * 鏁板瓧
+     */
+    MATH(UnsignedMathGenerator.class),
+
+    /**
+     * 瀛楃
+     */
+    CHAR(RandomGenerator.class);
+
+    private final Class<? extends CodeGenerator> clazz;
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatableFilter.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatableFilter.java
new file mode 100644
index 0000000..60e98ef
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatableFilter.java
@@ -0,0 +1,40 @@
+package com.ruoyi.common.web.filter;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import org.springframework.http.MediaType;
+
+import jakarta.servlet.*;
+import jakarta.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * Repeatable 杩囨护鍣�
+ *
+ * @author ruoyi
+ */
+public class RepeatableFilter implements Filter {
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws IOException, ServletException {
+        ServletRequest requestWrapper = null;
+        if (request instanceof HttpServletRequest
+            && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
+            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
+        }
+        if (null == requestWrapper) {
+            chain.doFilter(request, response);
+        } else {
+            chain.doFilter(requestWrapper, response);
+        }
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatedlyRequestWrapper.java
new file mode 100644
index 0000000..32e6658
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/RepeatedlyRequestWrapper.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.web.filter;
+
+import cn.hutool.core.io.IoUtil;
+import com.ruoyi.common.core.constant.Constants;
+
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.ServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * 鏋勫缓鍙噸澶嶈鍙杋nputStream鐨剅equest
+ *
+ * @author ruoyi
+ */
+public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
+    private final byte[] body;
+
+    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
+        super(request);
+        request.setCharacterEncoding(Constants.UTF8);
+        response.setCharacterEncoding(Constants.UTF8);
+
+        body = IoUtil.readBytes(request.getInputStream(), false);
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+        return new BufferedReader(new InputStreamReader(getInputStream()));
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+        return new ServletInputStream() {
+            @Override
+            public int read() throws IOException {
+                return bais.read();
+            }
+
+            @Override
+            public int available() throws IOException {
+                return body.length;
+            }
+
+            @Override
+            public boolean isFinished() {
+                return false;
+            }
+
+            @Override
+            public boolean isReady() {
+                return false;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+
+            }
+        };
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssFilter.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssFilter.java
new file mode 100644
index 0000000..a11660f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssFilter.java
@@ -0,0 +1,62 @@
+package com.ruoyi.common.web.filter;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import org.springframework.http.HttpMethod;
+
+import jakarta.servlet.*;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 闃叉XSS鏀诲嚮鐨勮繃婊ゅ櫒
+ *
+ * @author ruoyi
+ */
+public class XssFilter implements Filter {
+    /**
+     * 鎺掗櫎閾炬帴
+     */
+    public List<String> excludes = new ArrayList<>();
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        String tempExcludes = filterConfig.getInitParameter("excludes");
+        if (StringUtils.isNotEmpty(tempExcludes)) {
+            String[] url = tempExcludes.split(",");
+            for (int i = 0; url != null && i < url.length; i++) {
+                excludes.add(url[i]);
+            }
+        }
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws IOException, ServletException {
+        HttpServletRequest req = (HttpServletRequest) request;
+        HttpServletResponse resp = (HttpServletResponse) response;
+        if (handleExcludeURL(req, resp)) {
+            chain.doFilter(request, response);
+            return;
+        }
+        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
+        chain.doFilter(xssRequest, response);
+    }
+
+    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
+        String url = request.getServletPath();
+        String method = request.getMethod();
+        // GET DELETE 涓嶈繃婊�
+        if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) {
+            return true;
+        }
+        return StringUtils.matches(url, excludes);
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssHttpServletRequestWrapper.java
new file mode 100644
index 0000000..a7d9f1e
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/filter/XssHttpServletRequestWrapper.java
@@ -0,0 +1,97 @@
+package com.ruoyi.common.web.filter;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HtmlUtil;
+import com.ruoyi.common.core.utils.StringUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+
+import jakarta.servlet.ReadListener;
+import jakarta.servlet.ServletInputStream;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * XSS杩囨护澶勭悊
+ *
+ * @author ruoyi
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
+    /**
+     * @param request
+     */
+    public XssHttpServletRequestWrapper(HttpServletRequest request) {
+        super(request);
+    }
+
+    @Override
+    public String[] getParameterValues(String name) {
+        String[] values = super.getParameterValues(name);
+        if (values != null) {
+            int length = values.length;
+            String[] escapseValues = new String[length];
+            for (int i = 0; i < length; i++) {
+                // 闃瞲ss鏀诲嚮鍜岃繃婊ゅ墠鍚庣┖鏍�
+                escapseValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim();
+            }
+            return escapseValues;
+        }
+        return super.getParameterValues(name);
+    }
+
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+        // 闈瀓son绫诲瀷锛岀洿鎺ヨ繑鍥�
+        if (!isJsonRequest()) {
+            return super.getInputStream();
+        }
+
+        // 涓虹┖锛岀洿鎺ヨ繑鍥�
+        String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8);
+        if (StringUtils.isEmpty(json)) {
+            return super.getInputStream();
+        }
+
+        // xss杩囨护
+        json = HtmlUtil.cleanHtmlTag(json).trim();
+        byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
+        final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes);
+        return new ServletInputStream() {
+            @Override
+            public boolean isFinished() {
+                return true;
+            }
+
+            @Override
+            public boolean isReady() {
+                return true;
+            }
+
+            @Override
+            public int available() throws IOException {
+                return jsonBytes.length;
+            }
+
+            @Override
+            public void setReadListener(ReadListener readListener) {
+            }
+
+            @Override
+            public int read() throws IOException {
+                return bis.read();
+            }
+        };
+    }
+
+    /**
+     * 鏄惁鏄疛son璇锋眰
+     */
+    public boolean isJsonRequest() {
+        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
+        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/interceptor/PlusWebInvokeTimeInterceptor.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/interceptor/PlusWebInvokeTimeInterceptor.java
new file mode 100644
index 0000000..b9f8ddc
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/interceptor/PlusWebInvokeTimeInterceptor.java
@@ -0,0 +1,94 @@
+package com.ruoyi.common.web.interceptor;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.map.MapUtil;
+import com.alibaba.ttl.TransmittableThreadLocal;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.web.filter.RepeatedlyRequestWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.time.StopWatch;
+import org.springframework.http.MediaType;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.util.Map;
+
+/**
+ * web鐨勮皟鐢ㄦ椂闂寸粺璁℃嫤鎴櫒
+ * dev鐜鏈夋晥
+ *
+ * @author Lion Li
+ * @since 3.3.0
+ */
+@Slf4j
+public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
+
+    private final String prodProfile = "prod";
+
+    private final TransmittableThreadLocal<StopWatch> invokeTimeTL = new TransmittableThreadLocal<>();
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        if (!prodProfile.equals(SpringUtils.getActiveProfile())) {
+            String url = request.getMethod() + " " + request.getRequestURI();
+
+            // 鎵撳嵃璇锋眰鍙傛暟
+            if (isJsonRequest(request)) {
+                String jsonParam = "";
+                if (request instanceof RepeatedlyRequestWrapper) {
+                    BufferedReader reader = request.getReader();
+                    jsonParam = IoUtil.read(reader);
+                }
+                log.debug("[PLUS]寮�濮嬭姹� => URL[{}],鍙傛暟绫诲瀷[json],鍙傛暟:[{}]", url, jsonParam);
+            } else {
+                Map<String, String[]> parameterMap = request.getParameterMap();
+                if (MapUtil.isNotEmpty(parameterMap)) {
+                    String parameters = JsonUtils.toJsonString(parameterMap);
+                    log.debug("[PLUS]寮�濮嬭姹� => URL[{}],鍙傛暟绫诲瀷[param],鍙傛暟:[{}]", url, parameters);
+                } else {
+                    log.debug("[PLUS]寮�濮嬭姹� => URL[{}],鏃犲弬鏁�", url);
+                }
+            }
+
+            StopWatch stopWatch = new StopWatch();
+            invokeTimeTL.set(stopWatch);
+            stopWatch.start();
+        }
+        return true;
+    }
+
+    @Override
+    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        if (!prodProfile.equals(SpringUtils.getActiveProfile())) {
+            StopWatch stopWatch = invokeTimeTL.get();
+            stopWatch.stop();
+            log.debug("[PLUS]缁撴潫璇锋眰 => URL[{}],鑰楁椂:[{}]姣", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime());
+            invokeTimeTL.remove();
+        }
+    }
+
+    /**
+     * 鍒ゆ柇鏈璇锋眰鐨勬暟鎹被鍨嬫槸鍚︿负json
+     *
+     * @param request request
+     * @return boolean
+     */
+    private boolean isJsonRequest(HttpServletRequest request) {
+        String contentType = request.getContentType();
+        if (contentType != null) {
+            return StringUtils.startsWithIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE);
+        }
+        return false;
+    }
+
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/utils/UnsignedMathGenerator.java b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/utils/UnsignedMathGenerator.java
new file mode 100644
index 0000000..06c3f3c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/java/com/ruoyi/common/web/utils/UnsignedMathGenerator.java
@@ -0,0 +1,88 @@
+package com.ruoyi.common.web.utils;
+
+import cn.hutool.captcha.generator.CodeGenerator;
+import cn.hutool.core.math.Calculator;
+import cn.hutool.core.util.CharUtil;
+import cn.hutool.core.util.RandomUtil;
+import com.ruoyi.common.core.utils.StringUtils;
+
+import java.io.Serial;
+
+/**
+ * 鏃犵鍙疯绠楃敓鎴愬櫒
+ *
+ * @author Lion Li
+ */
+public class UnsignedMathGenerator implements CodeGenerator {
+
+    @Serial
+    private static final long serialVersionUID = -5514819971774091076L;
+
+    private static final String OPERATORS = "+-*";
+
+    /**
+     * 鍙備笌璁$畻鏁板瓧鏈�澶ч暱搴�
+     */
+    private final int numberLength;
+
+    /**
+     * 鏋勯��
+     */
+    public UnsignedMathGenerator() {
+        this(2);
+    }
+
+    /**
+     * 鏋勯��
+     *
+     * @param numberLength 鍙備笌璁$畻鏈�澶ф暟瀛椾綅鏁�
+     */
+    public UnsignedMathGenerator(int numberLength) {
+        this.numberLength = numberLength;
+    }
+
+    @Override
+    public String generate() {
+        final int limit = getLimit();
+        int a = RandomUtil.randomInt(limit);
+        int b = RandomUtil.randomInt(limit);
+        String max = Integer.toString(Math.max(a,b));
+        String min = Integer.toString(Math.min(a,b));
+        max = StringUtils.rightPad(max, this.numberLength, CharUtil.SPACE);
+        min = StringUtils.rightPad(min, this.numberLength, CharUtil.SPACE);
+
+        return max + RandomUtil.randomChar(OPERATORS) + min + '=';
+    }
+
+    @Override
+    public boolean verify(String code, String userInputCode) {
+        int result;
+        try {
+            result = Integer.parseInt(userInputCode);
+        } catch (NumberFormatException e) {
+            // 鐢ㄦ埛杈撳叆闈炴暟瀛�
+            return false;
+        }
+
+        final int calculateResult = (int) Calculator.conversion(code);
+        return result == calculateResult;
+    }
+
+    /**
+     * 鑾峰彇楠岃瘉鐮侀暱搴�
+     *
+     * @return 楠岃瘉鐮侀暱搴�
+     */
+    public int getLength() {
+        return this.numberLength * 2 + 2;
+    }
+
+    /**
+     * 鏍规嵁闀垮害鑾峰彇鍙備笌璁$畻鏁板瓧鏈�澶у��
+     *
+     * @return 鏈�澶у��
+     */
+    private int getLimit() {
+        return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
+    }
+}
diff --git a/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..cdf8c66
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,5 @@
+com.ruoyi.common.web.config.CaptchaConfig
+com.ruoyi.common.web.config.FilterConfig
+com.ruoyi.common.web.config.I18nConfig
+com.ruoyi.common.web.config.ResourcesConfig
+com.ruoyi.common.web.config.UndertowConfig
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/CellMerge.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/CellMerge.java
deleted file mode 100644
index 4af822e..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/CellMerge.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import com.ruoyi.common.excel.CellMergeStrategy;
-
-import java.lang.annotation.*;
-
-/**
- * excel 鍒楀崟鍏冩牸鍚堝苟(鍚堝苟鍒楃浉鍚岄」)
- *
- * 闇�鎼厤 {@link CellMergeStrategy} 绛栫暐浣跨敤
- *
- * @author Lion Li
- */
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-public @interface CellMerge {
-
-	/**
-	 * col index
-	 */
-	int index() default -1;
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java
deleted file mode 100644
index df416ed..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * 鏁版嵁鏉冮檺
- *
- * 涓�涓敞瑙e彧鑳藉搴斾竴涓ā鏉�
- *
- * @author Lion Li
- * @version 3.5.0
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface DataColumn {
-
-    /**
-     * 鍗犱綅绗﹀叧閿瓧
-     */
-    String[] key() default "deptName";
-
-    /**
-     * 鍗犱綅绗︽浛鎹㈠��
-     */
-    String[] value() default "dept_id";
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataPermission.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataPermission.java
deleted file mode 100644
index 73d9c03..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataPermission.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * 鏁版嵁鏉冮檺缁�
- *
- * @author Lion Li
- * @version 3.5.0
- */
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface DataPermission {
-
-    DataColumn[] value();
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java
deleted file mode 100644
index 5c14a55..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.ruoyi.common.jackson.DictDataJsonSerializer;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 瀛楀吀鏁版嵁鏄犲皠娉ㄨВ
- *
- * @author itino
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.FIELD, ElementType.METHOD})
-@JacksonAnnotationsInside
-@JsonSerialize(using = DictDataJsonSerializer.class)
-public @interface DictDataMapper {
-
-    /**
-     * 璁剧疆瀛楀吀鐨則ype鍊� (濡�: sys_user_sex)
-     */
-    String dictType() default "";
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java
deleted file mode 100644
index 400080e..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/ExcelDictFormat.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * 瀛楀吀鏍煎紡鍖�
- *
- * @author Lion Li
- */
-@Target({ElementType.FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-@Inherited
-public @interface ExcelDictFormat {
-
-    /**
-     * 濡傛灉鏄瓧鍏哥被鍨嬶紝璇疯缃瓧鍏哥殑type鍊� (濡�: sys_user_sex)
-     */
-    String dictType() default "";
-
-    /**
-     * 璇诲彇鍐呭杞〃杈惧紡 (濡�: 0=鐢�,1=濂�,2=鏈煡)
-     */
-    String readConverterExp() default "";
-
-    /**
-     * 鍒嗛殧绗︼紝璇诲彇瀛楃涓茬粍鍐呭
-     */
-    String separator() default ",";
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
deleted file mode 100644
index 32c39a3..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.enums.OperatorType;
-
-import java.lang.annotation.*;
-
-/**
- * 鑷畾涔夋搷浣滄棩蹇楄褰曟敞瑙�
- *
- * @author ruoyi
- */
-@Target({ElementType.PARAMETER, ElementType.METHOD})
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface Log {
-    /**
-     * 妯″潡
-     */
-    String title() default "";
-
-    /**
-     * 鍔熻兘
-     */
-    BusinessType businessType() default BusinessType.OTHER;
-
-    /**
-     * 鎿嶄綔浜虹被鍒�
-     */
-    OperatorType operatorType() default OperatorType.MANAGE;
-
-    /**
-     * 鏄惁淇濆瓨璇锋眰鐨勫弬鏁�
-     */
-    boolean isSaveRequestData() default true;
-
-    /**
-     * 鏄惁淇濆瓨鍝嶅簲鐨勫弬鏁�
-     */
-    boolean isSaveResponseData() default true;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
deleted file mode 100644
index 2e3ff7a..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.enums.LimitType;
-
-import java.lang.annotation.*;
-
-/**
- * 闄愭祦娉ㄨВ
- *
- * @author Lion Li
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface RateLimiter {
-    /**
-     * 闄愭祦key
-     */
-    String key() default CacheConstants.RATE_LIMIT_KEY;
-
-    /**
-     * 闄愭祦鏃堕棿,鍗曚綅绉�
-     */
-    int time() default 60;
-
-    /**
-     * 闄愭祦娆℃暟
-     */
-    int count() default 100;
-
-    /**
-     * 闄愭祦绫诲瀷
-     */
-    LimitType limitType() default LimitType.DEFAULT;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
deleted file mode 100644
index d30962d..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import java.lang.annotation.*;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
- *
- * @author Lion Li
- */
-@Inherited
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface RepeatSubmit {
-
-    /**
-     * 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦
-     */
-    int interval() default 5000;
-
-    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
-
-    /**
-     * 鎻愮ず娑堟伅 鏀寔鍥介檯鍖� 鏍煎紡涓� {code}
-     */
-    String message() default "{repeat.submit.message}";
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
deleted file mode 100644
index 2ad9777..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.common.annotation;
-
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.ruoyi.common.enums.SensitiveStrategy;
-import com.ruoyi.common.jackson.SensitiveJsonSerializer;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 鏁版嵁鑴辨晱娉ㄨВ
- *
- * @author zhujie
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-@JacksonAnnotationsInside
-@JsonSerialize(using = SensitiveJsonSerializer.class)
-public @interface Sensitive {
-    SensitiveStrategy strategy();
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/captcha/UnsignedMathGenerator.java b/ruoyi-common/src/main/java/com/ruoyi/common/captcha/UnsignedMathGenerator.java
deleted file mode 100644
index 022fefc..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/captcha/UnsignedMathGenerator.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.ruoyi.common.captcha;
-
-import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.core.math.Calculator;
-import cn.hutool.core.util.CharUtil;
-import cn.hutool.core.util.RandomUtil;
-import com.ruoyi.common.utils.StringUtils;
-
-import java.io.Serial;
-
-/**
- * 鏃犵鍙疯绠楃敓鎴愬櫒
- *
- * @author Lion Li
- */
-public class UnsignedMathGenerator implements CodeGenerator {
-
-    @Serial
-    private static final long serialVersionUID = -5514819971774091076L;
-
-    private static final String OPERATORS = "+-*";
-
-    /**
-     * 鍙備笌璁$畻鏁板瓧鏈�澶ч暱搴�
-     */
-    private final int numberLength;
-
-    /**
-     * 鏋勯��
-     */
-    public UnsignedMathGenerator() {
-        this(2);
-    }
-
-    /**
-     * 鏋勯��
-     *
-     * @param numberLength 鍙備笌璁$畻鏈�澶ф暟瀛椾綅鏁�
-     */
-    public UnsignedMathGenerator(int numberLength) {
-        this.numberLength = numberLength;
-    }
-
-    @Override
-    public String generate() {
-        final int limit = getLimit();
-        int a = RandomUtil.randomInt(limit);
-        int b = RandomUtil.randomInt(limit);
-        String max = Integer.toString(Math.max(a,b));
-        String min = Integer.toString(Math.min(a,b));
-        max = StringUtils.rightPad(max, this.numberLength, CharUtil.SPACE);
-        min = StringUtils.rightPad(min, this.numberLength, CharUtil.SPACE);
-
-        return max + RandomUtil.randomChar(OPERATORS) + min + '=';
-    }
-
-    @Override
-    public boolean verify(String code, String userInputCode) {
-        int result;
-        try {
-            result = Integer.parseInt(userInputCode);
-        } catch (NumberFormatException e) {
-            // 鐢ㄦ埛杈撳叆闈炴暟瀛�
-            return false;
-        }
-
-        final int calculateResult = (int) Calculator.conversion(code);
-        return result == calculateResult;
-    }
-
-    /**
-     * 鑾峰彇楠岃瘉鐮侀暱搴�
-     *
-     * @return 楠岃瘉鐮侀暱搴�
-     */
-    public int getLength() {
-        return this.numberLength * 2 + 2;
-    }
-
-    /**
-     * 鏍规嵁闀垮害鑾峰彇鍙備笌璁$畻鏁板瓧鏈�澶у��
-     *
-     * @return 鏈�澶у��
-     */
-    private int getLimit() {
-        return Integer.parseInt("1" + StringUtils.repeat('0', this.numberLength));
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
deleted file mode 100644
index 8ce7a8c..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.ruoyi.common.config;
-
-import lombok.Data;
-import lombok.Getter;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * 璇诲彇椤圭洰鐩稿叧閰嶇疆
- *
- * @author Lion Li
- */
-
-@Data
-@Component
-@ConfigurationProperties(prefix = "ruoyi")
-public class RuoYiConfig {
-
-    /**
-     * 椤圭洰鍚嶇О
-     */
-    private String name;
-
-    /**
-     * 鐗堟湰
-     */
-    private String version;
-
-    /**
-     * 鐗堟潈骞翠唤
-     */
-    private String copyrightYear;
-
-    /**
-     * 瀹炰緥婕旂ず寮�鍏�
-     */
-    private boolean demoEnabled;
-
-    /**
-     * 缂撳瓨鎳掑姞杞�
-     */
-    private boolean cacheLazy;
-
-    /**
-     * 鑾峰彇鍦板潃寮�鍏�
-     */
-    @Getter
-    private static boolean addressEnabled;
-
-    public void setAddressEnabled(boolean addressEnabled) {
-        RuoYiConfig.addressEnabled = addressEnabled;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
deleted file mode 100644
index 1cdf07e..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.ruoyi.common.constant;
-
-/**
- * 缂撳瓨鐨刱ey 甯搁噺
- *
- * @author ruoyi
- */
-public interface CacheConstants {
-
-    /**
-     * 鐧诲綍鐢ㄦ埛 redis key
-     */
-    String LOGIN_TOKEN_KEY = "Authorization:login:token:";
-
-    /**
-     * 鍦ㄧ嚎鐢ㄦ埛 redis key
-     */
-    String ONLINE_TOKEN_KEY = "online_tokens:";
-
-    /**
-     * 楠岃瘉鐮� redis key
-     */
-    String CAPTCHA_CODE_KEY = "captcha_codes:";
-
-    /**
-     * 鍙傛暟绠$悊 cache key
-     */
-    String SYS_CONFIG_KEY = "sys_config:";
-
-    /**
-     * 瀛楀吀绠$悊 cache key
-     */
-    String SYS_DICT_KEY = "sys_dict:";
-
-    /**
-     * 闃查噸鎻愪氦 redis key
-     */
-    String REPEAT_SUBMIT_KEY = "repeat_submit:";
-
-    /**
-     * 闄愭祦 redis key
-     */
-    String RATE_LIMIT_KEY = "rate_limit:";
-
-    /**
-     * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟 redis key
-     */
-    String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java
deleted file mode 100644
index 591ca25..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.ruoyi.common.constant;
-
-/**
- * 缂撳瓨缁勫悕绉板父閲�
- * <p>
- * key 鏍煎紡涓� cacheNames#ttl#maxIdleTime#maxSize
- * <p>
- * ttl 杩囨湡鏃堕棿 濡傛灉璁剧疆涓�0鍒欎笉杩囨湡 榛樿涓�0
- * maxIdleTime 鏈�澶х┖闂叉椂闂� 鏍规嵁LRU绠楁硶娓呯悊绌洪棽鏁版嵁 濡傛灉璁剧疆涓�0鍒欎笉妫�娴� 榛樿涓�0
- * maxSize 缁勬渶澶ч暱搴� 鏍规嵁LRU绠楁硶娓呯悊婧㈠嚭鏁版嵁 濡傛灉璁剧疆涓�0鍒欐棤闄愰暱 榛樿涓�0
- * <p>
- * 渚嬪瓙: test#60s銆乼est#0#60s銆乼est#0#1m#1000銆乼est#1h#0#500
- *
- * @author Lion Li
- */
-public interface CacheNames {
-
-    /**
-     * 婕旂ず妗堜緥
-     */
-    String DEMO_CACHE = "demo:cache#60s#10m#20";
-
-    /**
-     * 绯荤粺閰嶇疆
-     */
-    String SYS_CONFIG = "sys_config";
-
-    /**
-     * 鏁版嵁瀛楀吀
-     */
-    String SYS_DICT = "sys_dict";
-
-    /**
-     * OSS鍐呭
-     */
-    String SYS_OSS = "sys_oss#30d";
-
-    /**
-     * OSS閰嶇疆
-     */
-    String SYS_OSS_CONFIG = "sys_oss_config";
-
-    /**
-     * 鍦ㄧ嚎鐢ㄦ埛
-     */
-    String ONLINE_TOKEN = "online_tokens";
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
deleted file mode 100644
index e634ed2..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.ruoyi.common.constant;
-
-/**
- * 閫氱敤甯搁噺淇℃伅
- *
- * @author ruoyi
- */
-public interface Constants {
-
-    /**
-     * UTF-8 瀛楃闆�
-     */
-    String UTF8 = "UTF-8";
-
-    /**
-     * GBK 瀛楃闆�
-     */
-    String GBK = "GBK";
-
-    /**
-     * www涓诲煙
-     */
-    String WWW = "www.";
-
-    /**
-     * http璇锋眰
-     */
-    String HTTP = "http://";
-
-    /**
-     * https璇锋眰
-     */
-    String HTTPS = "https://";
-
-    /**
-     * 閫氱敤鎴愬姛鏍囪瘑
-     */
-    String SUCCESS = "0";
-
-    /**
-     * 閫氱敤澶辫触鏍囪瘑
-     */
-    String FAIL = "1";
-
-    /**
-     * 鐧诲綍鎴愬姛
-     */
-    String LOGIN_SUCCESS = "Success";
-
-    /**
-     * 娉ㄩ攢
-     */
-    String LOGOUT = "Logout";
-
-    /**
-     * 娉ㄥ唽
-     */
-    String REGISTER = "Register";
-
-    /**
-     * 鐧诲綍澶辫触
-     */
-    String LOGIN_FAIL = "Error";
-
-    /**
-     * 楠岃瘉鐮佹湁鏁堟湡锛堝垎閽燂級
-     */
-    Integer CAPTCHA_EXPIRATION = 2;
-
-    /**
-     * 浠ょ墝
-     */
-    String TOKEN = "token";
-
-}
-
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
deleted file mode 100644
index 1f622cd..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package com.ruoyi.common.constant;
-
-/**
- * 浠g爜鐢熸垚閫氱敤甯搁噺
- *
- * @author ruoyi
- */
-public interface GenConstants {
-    /**
-     * 鍗曡〃锛堝鍒犳敼鏌ワ級
-     */
-    String TPL_CRUD = "crud";
-
-    /**
-     * 鏍戣〃锛堝鍒犳敼鏌ワ級
-     */
-    String TPL_TREE = "tree";
-
-    /**
-     * 鏍戠紪鐮佸瓧娈�
-     */
-    String TREE_CODE = "treeCode";
-
-    /**
-     * 鏍戠埗缂栫爜瀛楁
-     */
-    String TREE_PARENT_CODE = "treeParentCode";
-
-    /**
-     * 鏍戝悕绉板瓧娈�
-     */
-    String TREE_NAME = "treeName";
-
-    /**
-     * 涓婄骇鑿滃崟ID瀛楁
-     */
-    String PARENT_MENU_ID = "parentMenuId";
-
-    /**
-     * 涓婄骇鑿滃崟鍚嶇О瀛楁
-     */
-    String PARENT_MENU_NAME = "parentMenuName";
-
-    /**
-     * 鏁版嵁搴撳瓧绗︿覆绫诲瀷
-     */
-    String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
-
-    /**
-     * 鏁版嵁搴撴枃鏈被鍨�
-     */
-    String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
-
-    /**
-     * 鏁版嵁搴撴椂闂寸被鍨�
-     */
-    String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
-
-    /**
-     * 鏁版嵁搴撴暟瀛楃被鍨�
-     */
-    String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
-        "bit", "bigint", "float", "double", "decimal"};
-
-    /**
-     * BO瀵硅薄 涓嶉渶瑕佹坊鍔犲瓧娈�
-     */
-    String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time", "del_flag", "update_by",
-        "update_time", "version"};
-
-    /**
-     * BO瀵硅薄 涓嶉渶瑕佺紪杈戝瓧娈�
-     */
-    String[] COLUMNNAME_NOT_EDIT = {"create_by", "create_time", "del_flag", "update_by",
-        "update_time", "version"};
-
-    /**
-     * VO瀵硅薄 涓嶉渶瑕佽繑鍥炲瓧娈�
-     */
-    String[] COLUMNNAME_NOT_LIST = {"create_by", "create_time", "del_flag", "update_by",
-        "update_time", "version"};
-
-    /**
-     * BO瀵硅薄 涓嶉渶瑕佹煡璇㈠瓧娈�
-     */
-    String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
-        "update_time", "remark", "version"};
-
-    /**
-     * Entity鍩虹被瀛楁
-     */
-    String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime"};
-
-    /**
-     * Tree鍩虹被瀛楁
-     */
-    String[] TREE_ENTITY = {"parentName", "parentId", "children"};
-
-    /**
-     * 鏂囨湰妗�
-     */
-    String HTML_INPUT = "input";
-
-    /**
-     * 鏂囨湰鍩�
-     */
-    String HTML_TEXTAREA = "textarea";
-
-    /**
-     * 涓嬫媺妗�
-     */
-    String HTML_SELECT = "select";
-
-    /**
-     * 鍗曢�夋
-     */
-    String HTML_RADIO = "radio";
-
-    /**
-     * 澶嶉�夋
-     */
-    String HTML_CHECKBOX = "checkbox";
-
-    /**
-     * 鏃ユ湡鎺т欢
-     */
-    String HTML_DATETIME = "datetime";
-
-    /**
-     * 鍥剧墖涓婁紶鎺т欢
-     */
-    String HTML_IMAGE_UPLOAD = "imageUpload";
-
-    /**
-     * 鏂囦欢涓婁紶鎺т欢
-     */
-    String HTML_FILE_UPLOAD = "fileUpload";
-
-    /**
-     * 瀵屾枃鏈帶浠�
-     */
-    String HTML_EDITOR = "editor";
-
-    /**
-     * 瀛楃涓茬被鍨�
-     */
-    String TYPE_STRING = "String";
-
-    /**
-     * 鏁村瀷
-     */
-    String TYPE_INTEGER = "Integer";
-
-    /**
-     * 闀挎暣鍨�
-     */
-    String TYPE_LONG = "Long";
-
-    /**
-     * 娴偣鍨�
-     */
-    String TYPE_DOUBLE = "Double";
-
-    /**
-     * 楂樼簿搴﹁绠楃被鍨�
-     */
-    String TYPE_BIGDECIMAL = "BigDecimal";
-
-    /**
-     * 鏃堕棿绫诲瀷
-     */
-    String TYPE_DATE = "Date";
-
-    /**
-     * 妯$硦鏌ヨ
-     */
-    String QUERY_LIKE = "LIKE";
-
-    /**
-     * 鐩哥瓑鏌ヨ
-     */
-    String QUERY_EQ = "EQ";
-
-    /**
-     * 闇�瑕�
-     */
-    String REQUIRE = "1";
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
deleted file mode 100644
index f007b8c..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.ruoyi.common.constant;
-
-/**
- * 杩斿洖鐘舵�佺爜
- *
- * @author Lion Li
- */
-public interface HttpStatus {
-    /**
-     * 鎿嶄綔鎴愬姛
-     */
-    int SUCCESS = 200;
-
-    /**
-     * 瀵硅薄鍒涘缓鎴愬姛
-     */
-    int CREATED = 201;
-
-    /**
-     * 璇锋眰宸茬粡琚帴鍙�
-     */
-    int ACCEPTED = 202;
-
-    /**
-     * 鎿嶄綔宸茬粡鎵ц鎴愬姛锛屼絾鏄病鏈夎繑鍥炴暟鎹�
-     */
-    int NO_CONTENT = 204;
-
-    /**
-     * 璧勬簮宸茶绉婚櫎
-     */
-    int MOVED_PERM = 301;
-
-    /**
-     * 閲嶅畾鍚�
-     */
-    int SEE_OTHER = 303;
-
-    /**
-     * 璧勬簮娌℃湁琚慨鏀�
-     */
-    int NOT_MODIFIED = 304;
-
-    /**
-     * 鍙傛暟鍒楄〃閿欒锛堢己灏戯紝鏍煎紡涓嶅尮閰嶏級
-     */
-    int BAD_REQUEST = 400;
-
-    /**
-     * 鏈巿鏉�
-     */
-    int UNAUTHORIZED = 401;
-
-    /**
-     * 璁块棶鍙楅檺锛屾巿鏉冭繃鏈�
-     */
-    int FORBIDDEN = 403;
-
-    /**
-     * 璧勬簮锛屾湇鍔℃湭鎵惧埌
-     */
-    int NOT_FOUND = 404;
-
-    /**
-     * 涓嶅厑璁哥殑http鏂规硶
-     */
-    int BAD_METHOD = 405;
-
-    /**
-     * 璧勬簮鍐茬獊锛屾垨鑰呰祫婧愯閿�
-     */
-    int CONFLICT = 409;
-
-    /**
-     * 涓嶆敮鎸佺殑鏁版嵁锛屽獟浣撶被鍨�
-     */
-    int UNSUPPORTED_TYPE = 415;
-
-    /**
-     * 绯荤粺鍐呴儴閿欒
-     */
-    int ERROR = 500;
-
-    /**
-     * 鎺ュ彛鏈疄鐜�
-     */
-    int NOT_IMPLEMENTED = 501;
-
-    /**
-     * 绯荤粺璀﹀憡娑堟伅
-     */
-    int WARN = 601;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
deleted file mode 100644
index 9f800be..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package com.ruoyi.common.constant;
-
-/**
- * 鐢ㄦ埛甯搁噺淇℃伅
- *
- * @author ruoyi
- */
-public interface UserConstants {
-
-    /**
-     * 骞冲彴鍐呯郴缁熺敤鎴风殑鍞竴鏍囧織
-     */
-    String SYS_USER = "SYS_USER";
-
-    /**
-     * 姝e父鐘舵��
-     */
-    String NORMAL = "0";
-
-    /**
-     * 寮傚父鐘舵��
-     */
-    String EXCEPTION = "1";
-
-    /**
-     * 鐢ㄦ埛姝e父鐘舵��
-     */
-    String USER_NORMAL = "0";
-
-    /**
-     * 鐢ㄦ埛灏佺鐘舵��
-     */
-    String USER_DISABLE = "1";
-
-    /**
-     * 瑙掕壊姝e父鐘舵��
-     */
-    String ROLE_NORMAL = "0";
-
-    /**
-     * 瑙掕壊灏佺鐘舵��
-     */
-    String ROLE_DISABLE = "1";
-
-    /**
-     * 閮ㄩ棬姝e父鐘舵��
-     */
-    String DEPT_NORMAL = "0";
-
-    /**
-     * 閮ㄩ棬鍋滅敤鐘舵��
-     */
-    String DEPT_DISABLE = "1";
-
-    /**
-     * 瀛楀吀姝e父鐘舵��
-     */
-    String DICT_NORMAL = "0";
-
-    /**
-     * 鏄惁涓虹郴缁熼粯璁わ紙鏄級
-     */
-    String YES = "Y";
-
-    /**
-     * 鏄惁鑿滃崟澶栭摼锛堟槸锛�
-     */
-    String YES_FRAME = "0";
-
-    /**
-     * 鏄惁鑿滃崟澶栭摼锛堝惁锛�
-     */
-    String NO_FRAME = "1";
-
-    /**
-     * 鑿滃崟姝e父鐘舵��
-     */
-    String MENU_NORMAL = "0";
-
-    /**
-     * 鑿滃崟鍋滅敤鐘舵��
-     */
-    String MENU_DISABLE = "1";
-
-    /**
-     * 鑿滃崟绫诲瀷锛堢洰褰曪級
-     */
-    String TYPE_DIR = "M";
-
-    /**
-     * 鑿滃崟绫诲瀷锛堣彍鍗曪級
-     */
-    String TYPE_MENU = "C";
-
-    /**
-     * 鑿滃崟绫诲瀷锛堟寜閽級
-     */
-    String TYPE_BUTTON = "F";
-
-    /**
-     * Layout缁勪欢鏍囪瘑
-     */
-    String LAYOUT = "Layout";
-
-    /**
-     * ParentView缁勪欢鏍囪瘑
-     */
-    String PARENT_VIEW = "ParentView";
-
-    /**
-     * InnerLink缁勪欢鏍囪瘑
-     */
-    String INNER_LINK = "InnerLink";
-
-    /**
-     * 鏍¢獙杩斿洖缁撴灉鐮�
-     */
-    String UNIQUE = "0";
-    String NOT_UNIQUE = "1";
-
-    /**
-     * 鐢ㄦ埛鍚嶉暱搴﹂檺鍒�
-     */
-    int USERNAME_MIN_LENGTH = 2;
-    int USERNAME_MAX_LENGTH = 20;
-
-    /**
-     * 瀵嗙爜闀垮害闄愬埗
-     */
-    int PASSWORD_MIN_LENGTH = 5;
-    int PASSWORD_MAX_LENGTH = 20;
-
-    /**
-     * 绠$悊鍛業D
-     */
-    Long ADMIN_ID = 1L;
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelBigNumberConvert.java b/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelBigNumberConvert.java
deleted file mode 100644
index 432ab74..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelBigNumberConvert.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.ruoyi.common.convert;
-
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.util.ObjectUtil;
-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;
-
-import java.math.BigDecimal;
-
-/**
- * 澶ф暟鍊艰浆鎹�
- * Excel 鏁板�奸暱搴︿綅15浣� 澶т簬15浣嶇殑鏁板�艰浆鎹綅瀛楃涓�
- *
- * @author Lion Li
- */
-@Slf4j
-public class ExcelBigNumberConvert implements Converter<Long> {
-
-    @Override
-    public Class<Long> supportJavaTypeKey() {
-        return Long.class;
-    }
-
-    @Override
-    public CellDataTypeEnum supportExcelTypeKey() {
-        return CellDataTypeEnum.STRING;
-    }
-
-    @Override
-    public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
-        return Convert.toLong(cellData.getData());
-    }
-
-    @Override
-    public WriteCellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
-        if (ObjectUtil.isNotNull(object)) {
-            String str = Convert.toStr(object);
-            if (str.length() > 15) {
-                return new WriteCellData<>(str);
-            }
-        }
-        WriteCellData<Object> cellData = new WriteCellData<>(new BigDecimal(object));
-        cellData.setType(CellDataTypeEnum.NUMBER);
-        return cellData;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelDictConvert.java b/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelDictConvert.java
deleted file mode 100644
index 03dad1f..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelDictConvert.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.ruoyi.common.convert;
-
-import cn.hutool.core.annotation.AnnotationUtil;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.util.ObjectUtil;
-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 com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.core.service.DictService;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-
-import java.lang.reflect.Field;
-
-/**
- * 瀛楀吀鏍煎紡鍖栬浆鎹㈠鐞�
- *
- * @author Lion Li
- */
-@Slf4j
-public class ExcelDictConvert implements Converter<Object> {
-
-    @Override
-    public Class<Object> supportJavaTypeKey() {
-        return Object.class;
-    }
-
-    @Override
-    public CellDataTypeEnum supportExcelTypeKey() {
-        return null;
-    }
-
-    @Override
-    public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
-        ExcelDictFormat anno = getAnnotation(contentProperty.getField());
-        String type = anno.dictType();
-        String label = cellData.getStringValue();
-        String value;
-        if (StringUtils.isBlank(type)) {
-            value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator());
-        } else {
-            value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator());
-        }
-        return Convert.convert(contentProperty.getField().getType(), value);
-    }
-
-    @Override
-    public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
-        if (ObjectUtil.isNull(object)) {
-            return new WriteCellData<>("");
-        }
-        ExcelDictFormat anno = getAnnotation(contentProperty.getField());
-        String type = anno.dictType();
-        String value = Convert.toStr(object);
-        String label;
-        if (StringUtils.isBlank(type)) {
-            label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator());
-        } else {
-            label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator());
-        }
-        return new WriteCellData<>(label);
-    }
-
-    private ExcelDictFormat getAnnotation(Field field) {
-        return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
deleted file mode 100644
index 1e0a5d5..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.ruoyi.common.core.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StringUtils;
-
-/**
- * web灞傞�氱敤鏁版嵁澶勭悊
- *
- * @author Lion Li
- */
-public class BaseController {
-
-    /**
-     * 鍝嶅簲杩斿洖缁撴灉
-     *
-     * @param rows 褰卞搷琛屾暟
-     * @return 鎿嶄綔缁撴灉
-     */
-    protected R<Void> toAjax(int rows) {
-        return rows > 0 ? R.ok() : R.fail();
-    }
-
-    /**
-     * 鍝嶅簲杩斿洖缁撴灉
-     *
-     * @param result 缁撴灉
-     * @return 鎿嶄綔缁撴灉
-     */
-    protected R<Void> toAjax(boolean result) {
-        return result ? R.ok() : R.fail();
-    }
-
-    /**
-     * 椤甸潰璺宠浆
-     */
-    public String redirect(String url) {
-        return StringUtils.format("redirect:{}", url);
-    }
-
-    /**
-     * 鑾峰彇鐢ㄦ埛缂撳瓨淇℃伅
-     */
-    public LoginUser getLoginUser() {
-        return LoginHelper.getLoginUser();
-    }
-
-    /**
-     * 鑾峰彇鐧诲綍鐢ㄦ埛id
-     */
-    public Long getUserId() {
-        return LoginHelper.getUserId();
-    }
-
-    /**
-     * 鑾峰彇鐧诲綍閮ㄩ棬id
-     */
-    public Long getDeptId() {
-        return LoginHelper.getDeptId();
-    }
-
-    /**
-     * 鑾峰彇鐧诲綍鐢ㄦ埛鍚�
-     */
-    public String getUsername() {
-        return LoginHelper.getUsername();
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
deleted file mode 100644
index 1917800..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.common.core.domain;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.Data;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Entity鍩虹被
- *
- * @author Lion Li
- */
-
-@Data
-public class BaseEntity implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鎼滅储鍊�
-     */
-    @JsonIgnore
-    @TableField(exist = false)
-    private String searchValue;
-
-    /**
-     * 鍒涘缓鑰�
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private String createBy;
-
-    /**
-     * 鍒涘缓鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT)
-    private Date createTime;
-
-    /**
-     * 鏇存柊鑰�
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private String updateBy;
-
-    /**
-     * 鏇存柊鏃堕棿
-     */
-    @TableField(fill = FieldFill.INSERT_UPDATE)
-    private Date updateTime;
-
-    /**
-     * 璇锋眰鍙傛暟
-     */
-    @JsonInclude(JsonInclude.Include.NON_EMPTY)
-    @TableField(exist = false)
-    private Map<String, Object> params = new HashMap<>();
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java
deleted file mode 100644
index 06f53a1..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.ruoyi.common.core.domain;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.metadata.OrderItem;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.sql.SqlUtil;
-import lombok.Data;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 鍒嗛〉鏌ヨ瀹炰綋绫�
- *
- * @author Lion Li
- */
-
-@Data
-public class PageQuery implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鍒嗛〉澶у皬
-     */
-    private Integer pageSize;
-
-    /**
-     * 褰撳墠椤垫暟
-     */
-    private Integer pageNum;
-
-    /**
-     * 鎺掑簭鍒�
-     */
-    private String orderByColumn;
-
-    /**
-     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
-     */
-    private String isAsc;
-
-    /**
-     * 褰撳墠璁板綍璧峰绱㈠紩 榛樿鍊�
-     */
-    public static final int DEFAULT_PAGE_NUM = 1;
-
-    /**
-     * 姣忛〉鏄剧ず璁板綍鏁� 榛樿鍊� 榛樿鏌ュ叏閮�
-     */
-    public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
-
-    public <T> Page<T> build() {
-        Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
-        Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
-        if (pageNum <= 0) {
-            pageNum = DEFAULT_PAGE_NUM;
-        }
-        Page<T> page = new Page<>(pageNum, pageSize);
-        List<OrderItem> orderItems = buildOrderItem();
-        if (CollUtil.isNotEmpty(orderItems)) {
-            page.addOrder(orderItems);
-        }
-        return page;
-    }
-
-    /**
-     * 鏋勫缓鎺掑簭
-     *
-     * 鏀寔鐨勭敤娉曞涓�:
-     * {isAsc:"asc",orderByColumn:"id"} order by id asc
-     * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc
-     * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc
-     * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc
-     */
-    private List<OrderItem> buildOrderItem() {
-        if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) {
-            return null;
-        }
-        String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
-        orderBy = StringUtils.toUnderScoreCase(orderBy);
-
-        // 鍏煎鍓嶇鎺掑簭绫诲瀷
-        isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"});
-
-        String[] orderByArr = orderBy.split(",");
-        String[] isAscArr = isAsc.split(",");
-        if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) {
-            throw new ServiceException("鎺掑簭鍙傛暟鏈夎");
-        }
-
-        List<OrderItem> list = new ArrayList<>();
-        // 姣忎釜瀛楁鍚勮嚜鎺掑簭
-        for (int i = 0; i < orderByArr.length; i++) {
-            String orderByStr = orderByArr[i];
-            String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i];
-            if ("asc".equals(isAscStr)) {
-                list.add(OrderItem.asc(orderByStr));
-            } else if ("desc".equals(isAscStr)) {
-                list.add(OrderItem.desc(orderByStr));
-            } else {
-                throw new ServiceException("鎺掑簭鍙傛暟鏈夎");
-            }
-        }
-        return list;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
deleted file mode 100644
index a31c323..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.ruoyi.common.core.domain;
-
-import com.ruoyi.common.constant.HttpStatus;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-
-/**
- * 鍝嶅簲淇℃伅涓讳綋
- *
- * @author Lion Li
- */
-@Data
-@NoArgsConstructor
-public class R<T> implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鎴愬姛
-     */
-    public static final int SUCCESS = 200;
-
-    /**
-     * 澶辫触
-     */
-    public static final int FAIL = 500;
-
-    private int code;
-
-    private String msg;
-
-    private T data;
-
-    public static <T> R<T> ok() {
-        return restResult(null, SUCCESS, "鎿嶄綔鎴愬姛");
-    }
-
-    public static <T> R<T> ok(T data) {
-        return restResult(data, SUCCESS, "鎿嶄綔鎴愬姛");
-    }
-
-    public static <T> R<T> ok(String msg) {
-        return restResult(null, SUCCESS, msg);
-    }
-
-    public static <T> R<T> ok(String msg, T data) {
-        return restResult(data, SUCCESS, msg);
-    }
-
-    public static <T> R<T> fail() {
-        return restResult(null, FAIL, "鎿嶄綔澶辫触");
-    }
-
-    public static <T> R<T> fail(String msg) {
-        return restResult(null, FAIL, msg);
-    }
-
-    public static <T> R<T> fail(T data) {
-        return restResult(data, FAIL, "鎿嶄綔澶辫触");
-    }
-
-    public static <T> R<T> fail(String msg, T data) {
-        return restResult(data, FAIL, msg);
-    }
-
-    public static <T> R<T> fail(int code, String msg) {
-        return restResult(null, code, msg);
-    }
-
-    /**
-     * 杩斿洖璀﹀憡娑堟伅
-     *
-     * @param msg 杩斿洖鍐呭
-     * @return 璀﹀憡娑堟伅
-     */
-    public static <T> R<T> warn(String msg) {
-        return restResult(null, HttpStatus.WARN, msg);
-    }
-
-    /**
-     * 杩斿洖璀﹀憡娑堟伅
-     *
-     * @param msg 杩斿洖鍐呭
-     * @param data 鏁版嵁瀵硅薄
-     * @return 璀﹀憡娑堟伅
-     */
-    public static <T> R<T> warn(String msg, T data) {
-        return restResult(data, HttpStatus.WARN, msg);
-    }
-
-    private static <T> R<T> restResult(T data, int code, String msg) {
-        R<T> r = new R<>();
-        r.setCode(code);
-        r.setData(data);
-        r.setMsg(msg);
-        return r;
-    }
-
-    public static <T> Boolean isError(R<T> ret) {
-        return !isSuccess(ret);
-    }
-
-    public static <T> Boolean isSuccess(R<T> ret) {
-        return R.SUCCESS == ret.getCode();
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
deleted file mode 100644
index 81053d6..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.common.core.domain;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serial;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tree鍩虹被
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class TreeEntity<T> extends BaseEntity {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鐖惰彍鍗曞悕绉�
-     */
-    @TableField(exist = false)
-    private String parentName;
-
-    /**
-     * 鐖惰彍鍗旾D
-     */
-    private Long parentId;
-
-    /**
-     * 瀛愰儴闂�
-     */
-    @TableField(exist = false)
-    private List<T> children = new ArrayList<>();
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/LogininforEvent.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/LogininforEvent.java
deleted file mode 100644
index c02e057..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/LogininforEvent.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.common.core.domain.event;
-
-import lombok.Data;
-
-import jakarta.servlet.http.HttpServletRequest;
-
-import java.io.Serial;
-import java.io.Serializable;
-
-/**
- * 鐧诲綍浜嬩欢
- *
- * @author Lion Li
- */
-
-@Data
-public class LogininforEvent implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鐢ㄦ埛璐﹀彿
-     */
-    private String username;
-
-    /**
-     * 鐧诲綍鐘舵�� 0鎴愬姛 1澶辫触
-     */
-    private String status;
-
-    /**
-     * 鎻愮ず娑堟伅
-     */
-    private String message;
-
-    /**
-     * 璇锋眰浣�
-     */
-    private HttpServletRequest request;
-
-    /**
-     * 鍏朵粬鍙傛暟
-     */
-    private Object[] args;
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/OperLogEvent.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/OperLogEvent.java
deleted file mode 100644
index 7ef44a1..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/event/OperLogEvent.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.common.core.domain.event;
-
-import lombok.Data;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * 鎿嶄綔鏃ュ織浜嬩欢
- *
- * @author Lion Li
- */
-
-@Data
-public class OperLogEvent implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鏃ュ織涓婚敭
-     */
-    private Long operId;
-
-    /**
-     * 鎿嶄綔妯″潡
-     */
-    private String title;
-
-    /**
-     * 涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛�
-     */
-    private Integer businessType;
-
-    /**
-     * 涓氬姟绫诲瀷鏁扮粍
-     */
-    private Integer[] businessTypes;
-
-    /**
-     * 璇锋眰鏂规硶
-     */
-    private String method;
-
-    /**
-     * 璇锋眰鏂瑰紡
-     */
-    private String requestMethod;
-
-    /**
-     * 鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級
-     */
-    private Integer operatorType;
-
-    /**
-     * 鎿嶄綔浜哄憳
-     */
-    private String operName;
-
-    /**
-     * 閮ㄩ棬鍚嶇О
-     */
-    private String deptName;
-
-    /**
-     * 璇锋眰url
-     */
-    private String operUrl;
-
-    /**
-     * 鎿嶄綔鍦板潃
-     */
-    private String operIp;
-
-    /**
-     * 鎿嶄綔鍦扮偣
-     */
-    private String operLocation;
-
-    /**
-     * 璇锋眰鍙傛暟
-     */
-    private String operParam;
-
-    /**
-     * 杩斿洖鍙傛暟
-     */
-    private String jsonResult;
-
-    /**
-     * 鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛�
-     */
-    private Integer status;
-
-    /**
-     * 閿欒娑堟伅
-     */
-    private String errorMsg;
-
-    /**
-     * 鎿嶄綔鏃堕棿
-     */
-    private Date operTime;
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
deleted file mode 100644
index aa1ea0b..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import com.ruoyi.common.constant.UserConstants;
-import lombok.Data;
-import org.hibernate.validator.constraints.Length;
-
-import jakarta.validation.constraints.NotBlank;
-
-/**
- * 鐢ㄦ埛鐧诲綍瀵硅薄
- *
- * @author Lion Li
- */
-
-@Data
-public class LoginBody {
-
-    /**
-     * 鐢ㄦ埛鍚�
-     */
-    @NotBlank(message = "{user.username.not.blank}")
-    @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
-    private String username;
-
-    /**
-     * 鐢ㄦ埛瀵嗙爜
-     */
-    @NotBlank(message = "{user.password.not.blank}")
-    @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
-    private String password;
-
-    /**
-     * 楠岃瘉鐮�
-     */
-    private String code;
-
-    /**
-     * 鍞竴鏍囪瘑
-     */
-    private String uuid;
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
deleted file mode 100644
index a680751..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.ruoyi.common.core.domain.model;
-
-import com.ruoyi.common.core.domain.dto.RoleDTO;
-import com.ruoyi.common.helper.LoginHelper;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.List;
-import java.util.Set;
-
-/**
- * 鐧诲綍鐢ㄦ埛韬唤鏉冮檺
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-public class LoginUser implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鐢ㄦ埛ID
-     */
-    private Long userId;
-
-    /**
-     * 閮ㄩ棬ID
-     */
-    private Long deptId;
-
-    /**
-     * 閮ㄩ棬鍚�
-     */
-    private String deptName;
-
-    /**
-     * 鐢ㄦ埛鍞竴鏍囪瘑
-     */
-    private String token;
-
-    /**
-     * 鐢ㄦ埛绫诲瀷
-     */
-    private String userType;
-
-    /**
-     * 鐧诲綍鏃堕棿
-     */
-    private Long loginTime;
-
-    /**
-     * 杩囨湡鏃堕棿
-     */
-    private Long expireTime;
-
-    /**
-     * 鐧诲綍IP鍦板潃
-     */
-    private String ipaddr;
-
-    /**
-     * 鐧诲綍鍦扮偣
-     */
-    private String loginLocation;
-
-    /**
-     * 娴忚鍣ㄧ被鍨�
-     */
-    private String browser;
-
-    /**
-     * 鎿嶄綔绯荤粺
-     */
-    private String os;
-
-    /**
-     * 鑿滃崟鏉冮檺
-     */
-    private Set<String> menuPermission;
-
-    /**
-     * 瑙掕壊鏉冮檺
-     */
-    private Set<String> rolePermission;
-
-    /**
-     * 鐢ㄦ埛鍚�
-     */
-    private String username;
-
-    /**
-     * 瑙掕壊瀵硅薄
-     */
-    private List<RoleDTO> roles;
-
-    /**
-     * 鏁版嵁鏉冮檺 褰撳墠瑙掕壊ID
-     */
-    private Long roleId;
-
-    /**
-     * 鑾峰彇鐧诲綍id
-     */
-    public String getLoginId() {
-        if (userType == null) {
-            throw new IllegalArgumentException("鐢ㄦ埛绫诲瀷涓嶈兘涓虹┖");
-        }
-        if (userId == null) {
-            throw new IllegalArgumentException("鐢ㄦ埛ID涓嶈兘涓虹┖");
-        }
-        return userType + LoginHelper.JOIN_CODE + userId;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java
deleted file mode 100644
index 0a8539a..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package com.ruoyi.common.core.mapper;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-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.*;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.toolkit.Db;
-import com.ruoyi.common.utils.BeanCopyUtils;
-import org.apache.ibatis.logging.Log;
-import org.apache.ibatis.logging.LogFactory;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鑷畾涔� Mapper 鎺ュ彛, 瀹炵幇 鑷畾涔夋墿灞�
- *
- * @param <M> mapper 娉涘瀷
- * @param <T> table 娉涘瀷
- * @param <V> vo 娉涘瀷
- * @author Lion Li
- * @since 2021-05-13
- */
-@SuppressWarnings("unchecked")
-public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
-
-    Log log = LogFactory.getLog(BaseMapperPlus.class);
-
-    default Class<V> currentVoClass() {
-        return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 2);
-    }
-
-    default Class<T> currentModelClass() {
-        return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 1);
-    }
-
-    default Class<M> currentMapperClass() {
-        return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), BaseMapperPlus.class, 0);
-    }
-
-    default List<T> selectList() {
-        return this.selectList(new QueryWrapper<>());
-    }
-
-    /**
-     * 鎵归噺鎻掑叆
-     */
-    default boolean insertBatch(Collection<T> entityList) {
-        return Db.saveBatch(entityList);
-    }
-
-    /**
-     * 鎵归噺鏇存柊
-     */
-    default boolean updateBatchById(Collection<T> entityList) {
-        return Db.updateBatchById(entityList);
-    }
-
-    /**
-     * 鎵归噺鎻掑叆鎴栨洿鏂�
-     */
-    default boolean insertOrUpdateBatch(Collection<T> entityList) {
-        return Db.saveOrUpdateBatch(entityList);
-    }
-
-    /**
-     * 鎵归噺鎻掑叆(鍖呭惈闄愬埗鏉℃暟)
-     */
-    default boolean insertBatch(Collection<T> entityList, int batchSize) {
-        return Db.saveBatch(entityList, batchSize);
-    }
-
-    /**
-     * 鎵归噺鏇存柊(鍖呭惈闄愬埗鏉℃暟)
-     */
-    default boolean updateBatchById(Collection<T> entityList, int batchSize) {
-        return Db.updateBatchById(entityList, batchSize);
-    }
-
-    /**
-     * 鎵归噺鎻掑叆鎴栨洿鏂�(鍖呭惈闄愬埗鏉℃暟)
-     */
-    default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
-        return Db.saveOrUpdateBatch(entityList, batchSize);
-    }
-
-    /**
-     * 鎻掑叆鎴栨洿鏂�(鍖呭惈闄愬埗鏉℃暟)
-     */
-    default boolean insertOrUpdate(T entity) {
-        return Db.saveOrUpdate(entity);
-    }
-
-    default V selectVoById(Serializable id) {
-        return selectVoById(id, this.currentVoClass());
-    }
-
-    /**
-     * 鏍规嵁 ID 鏌ヨ
-     */
-    default <C> C selectVoById(Serializable id, Class<C> voClass) {
-        T obj = this.selectById(id);
-        if (ObjectUtil.isNull(obj)) {
-            return null;
-        }
-        return BeanCopyUtils.copy(obj, voClass);
-    }
-
-    default List<V> selectVoBatchIds(Collection<? extends Serializable> idList) {
-        return selectVoBatchIds(idList, this.currentVoClass());
-    }
-
-    /**
-     * 鏌ヨ锛堟牴鎹甀D 鎵归噺鏌ヨ锛�
-     */
-    default <C> List<C> selectVoBatchIds(Collection<? extends Serializable> idList, Class<C> voClass) {
-        List<T> list = this.selectBatchIds(idList);
-        if (CollUtil.isEmpty(list)) {
-            return CollUtil.newArrayList();
-        }
-        return BeanCopyUtils.copyList(list, voClass);
-    }
-
-    default List<V> selectVoByMap(Map<String, Object> map) {
-        return selectVoByMap(map, this.currentVoClass());
-    }
-
-    /**
-     * 鏌ヨ锛堟牴鎹� columnMap 鏉′欢锛�
-     */
-    default <C> List<C> selectVoByMap(Map<String, Object> map, Class<C> voClass) {
-        List<T> list = this.selectByMap(map);
-        if (CollUtil.isEmpty(list)) {
-            return CollUtil.newArrayList();
-        }
-        return BeanCopyUtils.copyList(list, voClass);
-    }
-
-    default V selectVoOne(Wrapper<T> wrapper) {
-        return selectVoOne(wrapper, this.currentVoClass());
-    }
-
-    /**
-     * 鏍规嵁 entity 鏉′欢锛屾煡璇竴鏉¤褰�
-     */
-    default <C> C selectVoOne(Wrapper<T> wrapper, Class<C> voClass) {
-        T obj = this.selectOne(wrapper);
-        if (ObjectUtil.isNull(obj)) {
-            return null;
-        }
-        return BeanCopyUtils.copy(obj, voClass);
-    }
-
-    default List<V> selectVoList(Wrapper<T> wrapper) {
-        return selectVoList(wrapper, this.currentVoClass());
-    }
-
-    /**
-     * 鏍规嵁 entity 鏉′欢锛屾煡璇㈠叏閮ㄨ褰�
-     */
-    default <C> List<C> selectVoList(Wrapper<T> wrapper, Class<C> voClass) {
-        List<T> list = this.selectList(wrapper);
-        if (CollUtil.isEmpty(list)) {
-            return CollUtil.newArrayList();
-        }
-        return BeanCopyUtils.copyList(list, voClass);
-    }
-
-    default <P extends IPage<V>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper) {
-        return selectVoPage(page, wrapper, this.currentVoClass());
-    }
-
-    /**
-     * 鍒嗛〉鏌ヨVO
-     */
-    default <C, P extends IPage<C>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper, Class<C> voClass) {
-        IPage<T> pageData = this.selectPage(page, wrapper);
-        IPage<C> voPage = new Page<>(pageData.getCurrent(), pageData.getSize(), pageData.getTotal());
-        if (CollUtil.isEmpty(pageData.getRecords())) {
-            return (P) voPage;
-        }
-        voPage.setRecords(BeanCopyUtils.copyList(pageData.getRecords(), voClass));
-        return (P) voPage;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
deleted file mode 100644
index 8bfe049..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.ruoyi.common.core.page;
-
-import cn.hutool.http.HttpStatus;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * 琛ㄦ牸鍒嗛〉鏁版嵁瀵硅薄
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-public class TableDataInfo<T> implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鎬昏褰曟暟
-     */
-    private long total;
-
-    /**
-     * 鍒楄〃鏁版嵁
-     */
-    private List<T> rows;
-
-    /**
-     * 娑堟伅鐘舵�佺爜
-     */
-    private int code;
-
-    /**
-     * 娑堟伅鍐呭
-     */
-    private String msg;
-
-    /**
-     * 鍒嗛〉
-     *
-     * @param list  鍒楄〃鏁版嵁
-     * @param total 鎬昏褰曟暟
-     */
-    public TableDataInfo(List<T> list, long total) {
-        this.rows = list;
-        this.total = total;
-    }
-
-    public static <T> TableDataInfo<T> build(IPage<T> page) {
-        TableDataInfo<T> rspData = new TableDataInfo<>();
-        rspData.setCode(HttpStatus.HTTP_OK);
-        rspData.setMsg("鏌ヨ鎴愬姛");
-        rspData.setRows(page.getRecords());
-        rspData.setTotal(page.getTotal());
-        return rspData;
-    }
-
-    public static <T> TableDataInfo<T> build(List<T> list) {
-        TableDataInfo<T> rspData = new TableDataInfo<>();
-        rspData.setCode(HttpStatus.HTTP_OK);
-        rspData.setMsg("鏌ヨ鎴愬姛");
-        rspData.setRows(list);
-        rspData.setTotal(list.size());
-        return rspData;
-    }
-
-    public static <T> TableDataInfo<T> build() {
-        TableDataInfo<T> rspData = new TableDataInfo<>();
-        rspData.setCode(HttpStatus.HTTP_OK);
-        rspData.setMsg("鏌ヨ鎴愬姛");
-        return rspData;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
deleted file mode 100644
index ce32cb4..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.enums;
-
-/**
- * 鎿嶄綔鐘舵��
- *
- * @author ruoyi
- */
-public enum BusinessStatus {
-    /**
-     * 鎴愬姛
-     */
-    SUCCESS,
-
-    /**
-     * 澶辫触
-     */
-    FAIL,
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
deleted file mode 100644
index 2d2f2e4..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.ruoyi.common.enums;
-
-/**
- * 涓氬姟鎿嶄綔绫诲瀷
- *
- * @author ruoyi
- */
-public enum BusinessType {
-    /**
-     * 鍏跺畠
-     */
-    OTHER,
-
-    /**
-     * 鏂板
-     */
-    INSERT,
-
-    /**
-     * 淇敼
-     */
-    UPDATE,
-
-    /**
-     * 鍒犻櫎
-     */
-    DELETE,
-
-    /**
-     * 鎺堟潈
-     */
-    GRANT,
-
-    /**
-     * 瀵煎嚭
-     */
-    EXPORT,
-
-    /**
-     * 瀵煎叆
-     */
-    IMPORT,
-
-    /**
-     * 寮洪��
-     */
-    FORCE,
-
-    /**
-     * 鐢熸垚浠g爜
-     */
-    GENCODE,
-
-    /**
-     * 娓呯┖鏁版嵁
-     */
-    CLEAN,
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaCategory.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaCategory.java
deleted file mode 100644
index 35d3ea3..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaCategory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.ruoyi.common.enums;
-
-import cn.hutool.captcha.AbstractCaptcha;
-import cn.hutool.captcha.CircleCaptcha;
-import cn.hutool.captcha.LineCaptcha;
-import cn.hutool.captcha.ShearCaptcha;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 楠岃瘉鐮佺被鍒�
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum CaptchaCategory {
-
-    /**
-     * 绾挎骞叉壈
-     */
-    LINE(LineCaptcha.class),
-
-    /**
-     * 鍦嗗湀骞叉壈
-     */
-    CIRCLE(CircleCaptcha.class),
-
-    /**
-     * 鎵洸骞叉壈
-     */
-    SHEAR(ShearCaptcha.class);
-
-    private final Class<? extends AbstractCaptcha> clazz;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaType.java
deleted file mode 100644
index b1c50ca..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaType.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.common.enums;
-
-import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.captcha.generator.RandomGenerator;
-import com.ruoyi.common.captcha.UnsignedMathGenerator;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 楠岃瘉鐮佺被鍨�
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum CaptchaType {
-
-    /**
-     * 鏁板瓧
-     */
-    MATH(UnsignedMathGenerator.class),
-
-    /**
-     * 瀛楃
-     */
-    CHAR(RandomGenerator.class);
-
-    private final Class<? extends CodeGenerator> clazz;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataBaseType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataBaseType.java
deleted file mode 100644
index 5d0f05a..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataBaseType.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.ruoyi.common.enums;
-
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 鏁版嵁搴撶被鍨�
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum DataBaseType {
-
-    /**
-     * MySQL
-     */
-    MY_SQL("MySQL"),
-
-    /**
-     * Oracle
-     */
-    ORACLE("Oracle"),
-
-    /**
-     * PostgreSQL
-     */
-    POSTGRE_SQL("PostgreSQL"),
-
-    /**
-     * SQL Server
-     */
-    SQL_SERVER("Microsoft SQL Server");
-
-    private final String type;
-
-    public static DataBaseType find(String databaseProductName) {
-        if (StringUtils.isBlank(databaseProductName)) {
-            return null;
-        }
-        for (DataBaseType type : values()) {
-            if (type.getType().equals(databaseProductName)) {
-                return type;
-            }
-        }
-        return null;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java
deleted file mode 100644
index 6432465..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.ruoyi.common.enums;
-
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 鏁版嵁鏉冮檺绫诲瀷
- * <p>
- * 璇硶鏀寔 spel 妯℃澘琛ㄨ揪寮�
- * <p>
- * 鍐呯疆鏁版嵁 user 褰撳墠鐢ㄦ埛 鍐呭鍙傝�� LoginUser
- * 濡傞渶鎵╁睍鏁版嵁 鍙娇鐢� {@link com.ruoyi.common.helper.DataPermissionHelper} 鎿嶄綔
- * 鍐呯疆鏈嶅姟 sdss 绯荤粺鏁版嵁鏉冮檺鏈嶅姟 鍐呭鍙傝�� SysDataScopeService
- * 濡傞渶鎵╁睍鏇村鑷畾涔夋湇鍔� 鍙互鍙傝�� sdss 鑷缂栧啓
- *
- * @author Lion Li
- * @version 3.5.0
- */
-@Getter
-@AllArgsConstructor
-public enum DataScopeType {
-
-    /**
-     * 鍏ㄩ儴鏁版嵁鏉冮檺
-     */
-    ALL("1", "", ""),
-
-    /**
-     * 鑷畾鏁版嵁鏉冮檺
-     */
-    CUSTOM("2", " #{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} ) ", ""),
-
-    /**
-     * 閮ㄩ棬鏁版嵁鏉冮檺
-     */
-    DEPT("3", " #{#deptName} = #{#user.deptId} ", ""),
-
-    /**
-     * 閮ㄩ棬鍙婁互涓嬫暟鎹潈闄�
-     */
-    DEPT_AND_CHILD("4", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} )", ""),
-
-    /**
-     * 浠呮湰浜烘暟鎹潈闄�
-     */
-    SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 ");
-
-    private final String code;
-
-    /**
-     * 璇硶 閲囩敤 spel 妯℃澘琛ㄨ揪寮�
-     */
-    private final String sqlTemplate;
-
-    /**
-     * 涓嶆弧瓒� sqlTemplate 鍒欏~鍏�
-     */
-    private final String elseSql;
-
-    public static DataScopeType findCode(String code) {
-        if (StringUtils.isBlank(code)) {
-            return null;
-        }
-        for (DataScopeType type : values()) {
-            if (type.getCode().equals(code)) {
-                return type;
-            }
-        }
-        return null;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java
deleted file mode 100644
index 118a212..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.ruoyi.common.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 璁惧绫诲瀷
- * 閽堝涓�濂� 鐢ㄦ埛浣撶郴
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum DeviceType {
-
-    /**
-     * pc绔�
-     */
-    PC("pc"),
-
-    /**
-     * app绔�
-     */
-    APP("app"),
-
-    /**
-     * 灏忕▼搴忕
-     */
-    XCX("xcx");
-
-    private final String device;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
deleted file mode 100644
index bd1bfcc..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.ruoyi.common.enums;
-
-import org.springframework.lang.Nullable;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 璇锋眰鏂瑰紡
- *
- * @author ruoyi
- */
-public enum HttpMethod {
-    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
-
-    private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
-
-    static {
-        for (HttpMethod httpMethod : values()) {
-            mappings.put(httpMethod.name(), httpMethod);
-        }
-    }
-
-    @Nullable
-    public static HttpMethod resolve(@Nullable String method) {
-        return (method != null ? mappings.get(method) : null);
-    }
-
-    public boolean matches(String method) {
-        return (this == resolve(method));
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
deleted file mode 100644
index 897f706..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.common.enums;
-
-/**
- * 闄愭祦绫诲瀷
- *
- * @author ruoyi
- */
-
-public enum LimitType {
-    /**
-     * 榛樿绛栫暐鍏ㄥ眬闄愭祦
-     */
-    DEFAULT,
-
-    /**
-     * 鏍规嵁璇锋眰鑰匢P杩涜闄愭祦
-     */
-    IP,
-
-    /**
-     * 瀹炰緥闄愭祦(闆嗙兢澶氬悗绔疄渚�)
-     */
-    CLUSTER
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java
deleted file mode 100644
index c91a4b9..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.ruoyi.common.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 鐧诲綍绫诲瀷
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum LoginType {
-
-    /**
-     * 瀵嗙爜鐧诲綍
-     */
-    PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"),
-
-    /**
-     * 鐭俊鐧诲綍
-     */
-    SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"),
-
-    /**
-     * 灏忕▼搴忕櫥褰�
-     */
-    XCX("", "");
-
-    /**
-     * 鐧诲綍閲嶈瘯瓒呭嚭闄愬埗鎻愮ず
-     */
-    final String retryLimitExceed;
-
-    /**
-     * 鐧诲綍閲嶈瘯闄愬埗璁℃暟鎻愮ず
-     */
-    final String retryLimitCount;
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
deleted file mode 100644
index 3c4127d..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.ruoyi.common.enums;
-
-/**
- * 鎿嶄綔浜虹被鍒�
- *
- * @author ruoyi
- */
-public enum OperatorType {
-    /**
-     * 鍏跺畠
-     */
-    OTHER,
-
-    /**
-     * 鍚庡彴鐢ㄦ埛
-     */
-    MANAGE,
-
-    /**
-     * 鎵嬫満绔敤鎴�
-     */
-    MOBILE
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/SensitiveStrategy.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/SensitiveStrategy.java
deleted file mode 100644
index f667173..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/SensitiveStrategy.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.ruoyi.common.enums;
-
-import cn.hutool.core.util.DesensitizedUtil;
-import lombok.AllArgsConstructor;
-
-import java.util.function.Function;
-
-/**
- * 鑴辨晱绛栫暐
- *
- * @author Yjoioooo
- * @version 3.6.0
- */
-@AllArgsConstructor
-public enum SensitiveStrategy {
-
-    /**
-     * 韬唤璇佽劚鏁�
-     */
-    ID_CARD(s -> DesensitizedUtil.idCardNum(s, 3, 4)),
-
-    /**
-     * 鎵嬫満鍙疯劚鏁�
-     */
-    PHONE(DesensitizedUtil::mobilePhone),
-
-    /**
-     * 鍦板潃鑴辨晱
-     */
-    ADDRESS(s -> DesensitizedUtil.address(s, 8)),
-
-    /**
-     * 閭鑴辨晱
-     */
-    EMAIL(DesensitizedUtil::email),
-
-    /**
-     * 閾惰鍗�
-     */
-    BANK_CARD(DesensitizedUtil::bankCard);
-
-    //鍙嚜琛屾坊鍔犲叾浠栬劚鏁忕瓥鐣�
-
-    private final Function<String, String> desensitizer;
-
-    public Function<String, String> desensitizer() {
-        return desensitizer;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
deleted file mode 100644
index 673ddeb..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.common.enums;
-
-/**
- * 鐢ㄦ埛鐘舵��
- *
- * @author ruoyi
- */
-public enum UserStatus {
-    OK("0", "姝e父"), DISABLE("1", "鍋滅敤"), DELETED("2", "鍒犻櫎");
-
-    private final String code;
-    private final String info;
-
-    UserStatus(String code, String info) {
-        this.code = code;
-        this.info = info;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-    public String getInfo() {
-        return info;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserType.java
deleted file mode 100644
index ec6510d..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserType.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.ruoyi.common.enums;
-
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 璁惧绫诲瀷
- * 閽堝澶氬 鐢ㄦ埛浣撶郴
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum UserType {
-
-    /**
-     * pc绔�
-     */
-    SYS_USER("sys_user"),
-
-    /**
-     * app绔�
-     */
-    APP_USER("app_user");
-
-    private final String userType;
-
-    public static UserType getUserType(String str) {
-        for (UserType value : values()) {
-            if (StringUtils.contains(str, value.getUserType())) {
-                return value;
-            }
-        }
-        throw new RuntimeException("'UserType' not found By " + str);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java
deleted file mode 100644
index 6102eec..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/CellMergeStrategy.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.ruoyi.common.excel;
-
-import com.alibaba.excel.metadata.Head;
-import com.alibaba.excel.write.merge.AbstractMergeStrategy;
-import com.ruoyi.common.annotation.CellMerge;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.SneakyThrows;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.util.CellRangeAddress;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鍒楀�奸噸澶嶅悎骞剁瓥鐣�
- *
- * @author Lion Li
- */
-@AllArgsConstructor
-@Slf4j
-public class CellMergeStrategy extends AbstractMergeStrategy {
-
-	private List<?> list;
-	private boolean hasTitle;
-
-	@Override
-	protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
-		List<CellRangeAddress> cellList = handle(list, hasTitle);
-		// judge the list is not null
-		if (CollectionUtils.isNotEmpty(cellList)) {
-			// the judge is necessary
-			if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) {
-				for (CellRangeAddress item : cellList) {
-					sheet.addMergedRegion(item);
-				}
-			}
-		}
-	}
-
-	@SneakyThrows
-	private static List<CellRangeAddress> handle(List<?> list, boolean hasTitle) {
-		List<CellRangeAddress> cellList = new ArrayList<>();
-		if (CollectionUtils.isEmpty(list)) {
-			return cellList;
-		}
-		Class<?> clazz = list.get(0).getClass();
-		Field[] fields = clazz.getDeclaredFields();
-		// 鏈夋敞瑙g殑瀛楁
-		List<Field> mergeFields = new ArrayList<>();
-		List<Integer> mergeFieldsIndex = new ArrayList<>();
-		for (int i = 0; i < fields.length; i++) {
-			Field field = fields[i];
-			if (field.isAnnotationPresent(CellMerge.class)) {
-				CellMerge cm = field.getAnnotation(CellMerge.class);
-				mergeFields.add(field);
-				mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index());
-			}
-		}
-		// 琛屽悎骞跺紑濮嬩笅鏍�
-		int rowIndex = hasTitle ? 1 : 0;
-		Map<Field, RepeatCell> map = new HashMap<>();
-		// 鐢熸垚涓や袱鍚堝苟鍗曞厓鏍�
-		for (int i = 0; i < list.size(); i++) {
-			for (int j = 0; j < mergeFields.size(); j++) {
-				Field field = mergeFields.get(j);
-				String name = field.getName();
-				String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
-				Method readMethod = clazz.getMethod(methodName);
-				Object val = readMethod.invoke(list.get(i));
-
-				int colNum = mergeFieldsIndex.get(j);
-				if (!map.containsKey(field)) {
-					map.put(field, new RepeatCell(val, i));
-				} else {
-					RepeatCell repeatCell = map.get(field);
-					Object cellValue = repeatCell.getValue();
-					if (cellValue == null || "".equals(cellValue)) {
-						// 绌哄�艰烦杩囦笉鍚堝苟
-						continue;
-					}
-					if (!cellValue.equals(val)) {
-						if (i - repeatCell.getCurrent() > 1) {
-							cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
-						}
-						map.put(field, new RepeatCell(val, i));
-					} else if (i == list.size() - 1) {
-						if (i > repeatCell.getCurrent()) {
-							cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
-						}
-					}
-				}
-			}
-		}
-		return cellList;
-	}
-
-	@Data
-	@AllArgsConstructor
-	static class RepeatCell {
-
-		private Object value;
-
-		private int current;
-
-	}
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java
deleted file mode 100644
index a3243f9..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.common.excel;
-
-import cn.hutool.core.util.StrUtil;
-import com.alibaba.excel.context.AnalysisContext;
-import com.alibaba.excel.event.AnalysisEventListener;
-import com.alibaba.excel.exception.ExcelAnalysisException;
-import com.alibaba.excel.exception.ExcelDataConvertException;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.ValidatorUtils;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ConstraintViolationException;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Excel 瀵煎叆鐩戝惉
- *
- * @author Yjoioooo
- * @author Lion Li
- */
-@Slf4j
-@NoArgsConstructor
-public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {
-
-    /**
-     * 鏄惁Validator妫�楠岋紝榛樿涓烘槸
-     */
-    private Boolean isValidate = Boolean.TRUE;
-
-    /**
-     * excel 琛ㄥご鏁版嵁
-     */
-    private Map<Integer, String> headMap;
-
-    /**
-     * 瀵煎叆鍥炴墽
-     */
-    private ExcelResult<T> excelResult;
-
-    public DefaultExcelListener(boolean isValidate) {
-        this.excelResult = new DefautExcelResult<>();
-        this.isValidate = isValidate;
-    }
-
-    /**
-     * 澶勭悊寮傚父
-     *
-     * @param exception ExcelDataConvertException
-     * @param context   Excel 涓婁笅鏂�
-     */
-    @Override
-    public void onException(Exception exception, AnalysisContext context) throws Exception {
-        String errMsg = null;
-        if (exception instanceof ExcelDataConvertException) {
-            // 濡傛灉鏄煇涓�涓崟鍏冩牸鐨勮浆鎹㈠紓甯� 鑳借幏鍙栧埌鍏蜂綋琛屽彿
-            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
-            Integer rowIndex = excelDataConvertException.getRowIndex();
-            Integer columnIndex = excelDataConvertException.getColumnIndex();
-            errMsg = StrUtil.format("绗瑊}琛�-绗瑊}鍒�-琛ㄥご{}: 瑙f瀽寮傚父<br/>",
-                rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));
-            if (log.isDebugEnabled()) {
-                log.error(errMsg);
-            }
-        }
-        if (exception instanceof ConstraintViolationException) {
-            ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
-            Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
-            String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", ");
-            errMsg = StrUtil.format("绗瑊}琛屾暟鎹牎楠屽紓甯�: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);
-            if (log.isDebugEnabled()) {
-                log.error(errMsg);
-            }
-        }
-        excelResult.getErrorList().add(errMsg);
-        throw new ExcelAnalysisException(errMsg);
-    }
-
-    @Override
-    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
-        this.headMap = headMap;
-        log.debug("瑙f瀽鍒颁竴鏉¤〃澶存暟鎹�: {}", JsonUtils.toJsonString(headMap));
-    }
-
-    @Override
-    public void invoke(T data, AnalysisContext context) {
-        if (isValidate) {
-            ValidatorUtils.validate(data);
-        }
-        excelResult.getList().add(data);
-    }
-
-    @Override
-    public void doAfterAllAnalysed(AnalysisContext context) {
-        log.debug("鎵�鏈夋暟鎹В鏋愬畬鎴愶紒");
-    }
-
-    @Override
-    public ExcelResult<T> getExcelResult() {
-        return excelResult;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefautExcelResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefautExcelResult.java
deleted file mode 100644
index c852ce6..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefautExcelResult.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.ruoyi.common.excel;
-
-import cn.hutool.core.util.StrUtil;
-import lombok.Setter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 榛樿excel杩斿洖瀵硅薄
- *
- * @author Yjoioooo
- * @author Lion Li
- */
-public class DefautExcelResult<T> implements ExcelResult<T> {
-
-    /**
-     * 鏁版嵁瀵硅薄list
-     */
-    @Setter
-    private List<T> list;
-
-    /**
-     * 閿欒淇℃伅鍒楄〃
-     */
-    @Setter
-    private List<String> errorList;
-
-    public DefautExcelResult() {
-        this.list = new ArrayList<>();
-        this.errorList = new ArrayList<>();
-    }
-
-    public DefautExcelResult(List<T> list, List<String> errorList) {
-        this.list = list;
-        this.errorList = errorList;
-    }
-
-    public DefautExcelResult(ExcelResult<T> excelResult) {
-        this.list = excelResult.getList();
-        this.errorList = excelResult.getErrorList();
-    }
-
-    @Override
-    public List<T> getList() {
-        return list;
-    }
-
-    @Override
-    public List<String> getErrorList() {
-        return errorList;
-    }
-
-    /**
-     * 鑾峰彇瀵煎叆鍥炴墽
-     *
-     * @return 瀵煎叆鍥炴墽
-     */
-    @Override
-    public String getAnalysis() {
-        int successCount = list.size();
-        int errorCount = errorList.size();
-        if (successCount == 0) {
-            return "璇诲彇澶辫触锛屾湭瑙f瀽鍒版暟鎹�";
-        } else {
-            if (errorCount == 0) {
-                return StrUtil.format("鎭枩鎮紝鍏ㄩ儴璇诲彇鎴愬姛锛佸叡{}鏉�", successCount);
-            } else {
-                return "";
-            }
-        }
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelListener.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelListener.java
deleted file mode 100644
index 2064cad..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelListener.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.ruoyi.common.excel;
-
-import com.alibaba.excel.read.listener.ReadListener;
-
-/**
- * Excel 瀵煎叆鐩戝惉
- *
- * @author Lion Li
- */
-public interface ExcelListener<T> extends ReadListener<T> {
-
-    ExcelResult<T> getExcelResult();
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelResult.java
deleted file mode 100644
index 63f8b8a..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/ExcelResult.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.common.excel;
-
-import java.util.List;
-
-/**
- * excel杩斿洖瀵硅薄
- *
- * @author Lion Li
- */
-public interface ExcelResult<T> {
-
-    /**
-     * 瀵硅薄鍒楄〃
-     */
-    List<T> getList();
-
-    /**
-     * 閿欒鍒楄〃
-     */
-    List<String> getErrorList();
-
-    /**
-     * 瀵煎叆鍥炴墽
-     */
-    String getAnalysis();
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
deleted file mode 100644
index 0b12e09..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.ruoyi.common.exception;
-
-import java.io.Serial;
-
-/**
- * 婕旂ず妯″紡寮傚父
- *
- * @author ruoyi
- */
-public class DemoModeException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public DemoModeException() {
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
deleted file mode 100644
index bea24cc..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.ruoyi.common.exception;
-
-import java.io.Serial;
-
-/**
- * 鍏ㄥ眬寮傚父
- *
- * @author ruoyi
- */
-public class GlobalException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 閿欒鎻愮ず
-     */
-    private String message;
-
-    /**
-     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
-     */
-    private String detailMessage;
-
-    /**
-     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
-     */
-    public GlobalException() {
-    }
-
-    public GlobalException(String message) {
-        this.message = message;
-    }
-
-    public String getDetailMessage() {
-        return detailMessage;
-    }
-
-    public GlobalException setDetailMessage(String detailMessage) {
-        this.detailMessage = detailMessage;
-        return this;
-    }
-
-    @Override
-    public String getMessage() {
-        return message;
-    }
-
-    public GlobalException setMessage(String message) {
-        this.message = message;
-        return this;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
deleted file mode 100644
index 57063bf..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.ruoyi.common.exception;
-
-import java.io.Serial;
-
-/**
- * 涓氬姟寮傚父
- *
- * @author ruoyi
- */
-public final class ServiceException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 閿欒鐮�
-     */
-    private Integer code;
-
-    /**
-     * 閿欒鎻愮ず
-     */
-    private String message;
-
-    /**
-     * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
-     */
-    private String detailMessage;
-
-    /**
-     * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
-     */
-    public ServiceException() {
-    }
-
-    public ServiceException(String message) {
-        this.message = message;
-    }
-
-    public ServiceException(String message, Integer code) {
-        this.message = message;
-        this.code = code;
-    }
-
-    public String getDetailMessage() {
-        return detailMessage;
-    }
-
-    @Override
-    public String getMessage() {
-        return message;
-    }
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public ServiceException setMessage(String message) {
-        this.message = message;
-        return this;
-    }
-
-    public ServiceException setDetailMessage(String detailMessage) {
-        this.detailMessage = detailMessage;
-        return this;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
deleted file mode 100644
index 3452fc1..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.common.exception;
-
-import java.io.Serial;
-
-/**
- * 宸ュ叿绫诲紓甯�
- *
- * @author ruoyi
- */
-public class UtilException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 8247610319171014183L;
-
-    public UtilException(Throwable e) {
-        super(e.getMessage(), e);
-    }
-
-    public UtilException(String message) {
-        super(message);
-    }
-
-    public UtilException(String message, Throwable throwable) {
-        super(message, throwable);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
deleted file mode 100644
index e7a9288..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.ruoyi.common.exception.base;
-
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-
-/**
- * 鍩虹寮傚父
- *
- * @author ruoyi
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@NoArgsConstructor
-public class BaseException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鎵�灞炴ā鍧�
-     */
-    private String module;
-
-    /**
-     * 閿欒鐮�
-     */
-    private String code;
-
-    /**
-     * 閿欒鐮佸搴旂殑鍙傛暟
-     */
-    private Object[] args;
-
-    /**
-     * 閿欒娑堟伅
-     */
-    private String defaultMessage;
-
-    public BaseException(String module, String code, Object[] args, String defaultMessage) {
-        this.module = module;
-        this.code = code;
-        this.args = args;
-        this.defaultMessage = defaultMessage;
-    }
-
-    public BaseException(String module, String code, Object[] args) {
-        this(module, code, args, null);
-    }
-
-    public BaseException(String module, String defaultMessage) {
-        this(module, null, null, defaultMessage);
-    }
-
-    public BaseException(String code, Object[] args) {
-        this(null, code, args, null);
-    }
-
-    public BaseException(String defaultMessage) {
-        this(null, null, null, defaultMessage);
-    }
-
-    @Override
-    public String getMessage() {
-        String message = null;
-        if (!StringUtils.isEmpty(code)) {
-            message = MessageUtils.message(code, args);
-        }
-        if (message == null) {
-            message = defaultMessage;
-        }
-        return message;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
deleted file mode 100644
index e5542bb..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ruoyi.common.exception.file;
-
-import com.ruoyi.common.exception.base.BaseException;
-
-import java.io.Serial;
-
-/**
- * 鏂囦欢淇℃伅寮傚父绫�
- *
- * @author ruoyi
- */
-public class FileException extends BaseException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public FileException(String code, Object[] args) {
-        super("file", code, args, null);
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
deleted file mode 100644
index 44bcea5..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.exception.file;
-
-import java.io.Serial;
-
-/**
- * 鏂囦欢鍚嶇О瓒呴暱闄愬埗寮傚父绫�
- *
- * @author ruoyi
- */
-public class FileNameLengthLimitExceededException extends FileException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public FileNameLengthLimitExceededException(int defaultFileNameLength) {
-        super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
deleted file mode 100644
index 9127428..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.exception.file;
-
-import java.io.Serial;
-
-/**
- * 鏂囦欢鍚嶅ぇ灏忛檺鍒跺紓甯哥被
- *
- * @author ruoyi
- */
-public class FileSizeLimitExceededException extends FileException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public FileSizeLimitExceededException(long defaultMaxSize) {
-        super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
deleted file mode 100644
index a2765e5..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.exception.user;
-
-import java.io.Serial;
-
-/**
- * 楠岃瘉鐮侀敊璇紓甯哥被
- *
- * @author ruoyi
- */
-public class CaptchaException extends UserException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public CaptchaException() {
-        super("user.jcaptcha.error");
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
deleted file mode 100644
index b3beef8..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.exception.user;
-
-import java.io.Serial;
-
-/**
- * 楠岃瘉鐮佸け鏁堝紓甯哥被
- *
- * @author ruoyi
- */
-public class CaptchaExpireException extends UserException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public CaptchaExpireException() {
-        super("user.jcaptcha.expire");
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
deleted file mode 100644
index 632bf24..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.ruoyi.common.exception.user;
-
-import com.ruoyi.common.exception.base.BaseException;
-
-import java.io.Serial;
-
-/**
- * 鐢ㄦ埛淇℃伅寮傚父绫�
- *
- * @author ruoyi
- */
-public class UserException extends BaseException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public UserException(String code, Object... args) {
-        super("user", code, args, null);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
deleted file mode 100644
index b30408e..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.ruoyi.common.exception.user;
-
-import java.io.Serial;
-
-/**
- * 鐢ㄦ埛瀵嗙爜涓嶆纭垨涓嶇鍚堣鑼冨紓甯哥被
- *
- * @author ruoyi
- */
-public class UserPasswordNotMatchException extends UserException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public UserPasswordNotMatchException() {
-        super("user.password.not.match");
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
deleted file mode 100644
index 70c8897..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ruoyi.common.exception.user;
-
-import java.io.Serial;
-
-/**
- * 鐢ㄦ埛閿欒鏈�澶ф鏁板紓甯哥被
- *
- * @author ruoyi
- */
-public class UserPasswordRetryLimitExceedException extends UserException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) {
-        super("user.password.retry.limit.exceed", retryLimitCount, lockTime);
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
deleted file mode 100644
index 72587e2..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.ruoyi.common.filter;
-
-import com.ruoyi.common.utils.StringUtils;
-import org.springframework.http.MediaType;
-
-import jakarta.servlet.*;
-import jakarta.servlet.http.HttpServletRequest;
-import java.io.IOException;
-
-/**
- * Repeatable 杩囨护鍣�
- *
- * @author ruoyi
- */
-public class RepeatableFilter implements Filter {
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-
-    }
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
-        throws IOException, ServletException {
-        ServletRequest requestWrapper = null;
-        if (request instanceof HttpServletRequest
-            && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
-            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
-        }
-        if (null == requestWrapper) {
-            chain.doFilter(request, response);
-        } else {
-            chain.doFilter(requestWrapper, response);
-        }
-    }
-
-    @Override
-    public void destroy() {
-
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
deleted file mode 100644
index da04e54..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.ruoyi.common.filter;
-
-import cn.hutool.core.io.IoUtil;
-import com.ruoyi.common.constant.Constants;
-
-import jakarta.servlet.ReadListener;
-import jakarta.servlet.ServletInputStream;
-import jakarta.servlet.ServletResponse;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletRequestWrapper;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-/**
- * 鏋勫缓鍙噸澶嶈鍙杋nputStream鐨剅equest
- *
- * @author ruoyi
- */
-public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
-    private final byte[] body;
-
-    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
-        super(request);
-        request.setCharacterEncoding(Constants.UTF8);
-        response.setCharacterEncoding(Constants.UTF8);
-
-        body = IoUtil.readBytes(request.getInputStream(), false);
-    }
-
-    @Override
-    public BufferedReader getReader() throws IOException {
-        return new BufferedReader(new InputStreamReader(getInputStream()));
-    }
-
-    @Override
-    public ServletInputStream getInputStream() throws IOException {
-        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
-        return new ServletInputStream() {
-            @Override
-            public int read() throws IOException {
-                return bais.read();
-            }
-
-            @Override
-            public int available() throws IOException {
-                return body.length;
-            }
-
-            @Override
-            public boolean isFinished() {
-                return false;
-            }
-
-            @Override
-            public boolean isReady() {
-                return false;
-            }
-
-            @Override
-            public void setReadListener(ReadListener readListener) {
-
-            }
-        };
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
deleted file mode 100644
index cd35510..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ruoyi.common.filter;
-
-import com.ruoyi.common.enums.HttpMethod;
-import com.ruoyi.common.utils.StringUtils;
-
-import jakarta.servlet.*;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 闃叉XSS鏀诲嚮鐨勮繃婊ゅ櫒
- *
- * @author ruoyi
- */
-public class XssFilter implements Filter {
-    /**
-     * 鎺掗櫎閾炬帴
-     */
-    public List<String> excludes = new ArrayList<>();
-
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-        String tempExcludes = filterConfig.getInitParameter("excludes");
-        if (StringUtils.isNotEmpty(tempExcludes)) {
-            String[] url = tempExcludes.split(",");
-            for (int i = 0; url != null && i < url.length; i++) {
-                excludes.add(url[i]);
-            }
-        }
-    }
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
-        throws IOException, ServletException {
-        HttpServletRequest req = (HttpServletRequest) request;
-        HttpServletResponse resp = (HttpServletResponse) response;
-        if (handleExcludeURL(req, resp)) {
-            chain.doFilter(request, response);
-            return;
-        }
-        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
-        chain.doFilter(xssRequest, response);
-    }
-
-    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
-        String url = request.getServletPath();
-        String method = request.getMethod();
-        // GET DELETE 涓嶈繃婊�
-        if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) {
-            return true;
-        }
-        return StringUtils.matches(url, excludes);
-    }
-
-    @Override
-    public void destroy() {
-
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
deleted file mode 100644
index 55cba67..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.ruoyi.common.filter;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.http.HtmlUtil;
-import com.ruoyi.common.utils.StringUtils;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-
-import jakarta.servlet.ReadListener;
-import jakarta.servlet.ServletInputStream;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletRequestWrapper;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-/**
- * XSS杩囨护澶勭悊
- *
- * @author ruoyi
- */
-public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
-    /**
-     * @param request
-     */
-    public XssHttpServletRequestWrapper(HttpServletRequest request) {
-        super(request);
-    }
-
-    @Override
-    public String[] getParameterValues(String name) {
-        String[] values = super.getParameterValues(name);
-        if (values != null) {
-            int length = values.length;
-            String[] escapesValues = new String[length];
-            for (int i = 0; i < length; i++) {
-                // 闃瞲ss鏀诲嚮鍜岃繃婊ゅ墠鍚庣┖鏍�
-                escapesValues[i] = HtmlUtil.cleanHtmlTag(values[i]).trim();
-            }
-            return escapesValues;
-        }
-        return super.getParameterValues(name);
-    }
-
-    @Override
-    public ServletInputStream getInputStream() throws IOException {
-        // 闈瀓son绫诲瀷锛岀洿鎺ヨ繑鍥�
-        if (!isJsonRequest()) {
-            return super.getInputStream();
-        }
-
-        // 涓虹┖锛岀洿鎺ヨ繑鍥�
-        String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8);
-        if (StringUtils.isEmpty(json)) {
-            return super.getInputStream();
-        }
-
-        // xss杩囨护
-        json = HtmlUtil.cleanHtmlTag(json).trim();
-        byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
-        final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes);
-        return new ServletInputStream() {
-            @Override
-            public boolean isFinished() {
-                return true;
-            }
-
-            @Override
-            public boolean isReady() {
-                return true;
-            }
-
-            @Override
-            public int available() throws IOException {
-                return jsonBytes.length;
-            }
-
-            @Override
-            public void setReadListener(ReadListener readListener) {
-            }
-
-            @Override
-            public int read() throws IOException {
-                return bis.read();
-            }
-        };
-    }
-
-    /**
-     * 鏄惁鏄疛son璇锋眰
-     */
-    public boolean isJsonRequest() {
-        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
-        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataBaseHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataBaseHelper.java
deleted file mode 100644
index 1960356..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataBaseHelper.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.ruoyi.common.helper;
-
-import cn.hutool.core.convert.Convert;
-import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
-import com.ruoyi.common.enums.DataBaseType;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.SQLException;
-
-/**
- * 鏁版嵁搴撳姪鎵�
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class DataBaseHelper {
-
-    private static final DynamicRoutingDataSource DS = SpringUtils.getBean(DynamicRoutingDataSource.class);
-
-    /**
-     * 鑾峰彇褰撳墠鏁版嵁搴撶被鍨�
-     */
-    public static DataBaseType getDataBaseType() {
-        DataSource dataSource = DS.determineDataSource();
-        try (Connection conn = dataSource.getConnection()) {
-            DatabaseMetaData metaData = conn.getMetaData();
-            String databaseProductName = metaData.getDatabaseProductName();
-            return DataBaseType.find(databaseProductName);
-        } catch (SQLException e) {
-            throw new ServiceException(e.getMessage());
-        }
-    }
-
-    public static boolean isMySql() {
-        return DataBaseType.MY_SQL == getDataBaseType();
-    }
-
-    public static boolean isOracle() {
-        return DataBaseType.ORACLE == getDataBaseType();
-    }
-
-    public static boolean isPostgerSql() {
-        return DataBaseType.POSTGRE_SQL == getDataBaseType();
-    }
-
-    public static boolean isSqlServer() {
-        return DataBaseType.SQL_SERVER == getDataBaseType();
-    }
-
-    public static String findInSet(Object var1, String var2) {
-        DataBaseType dataBasyType = getDataBaseType();
-        String var = Convert.toStr(var1);
-        if (dataBasyType == DataBaseType.SQL_SERVER) {
-            // charindex(',100,' , ',0,100,101,') <> 0
-            return "charindex('," + var + ",' , ','+" + var2 + "+',') <> 0";
-        } else if (dataBasyType == DataBaseType.POSTGRE_SQL) {
-            // (select position(',100,' in ',0,100,101,')) <> 0
-            return "(select position('," + var + ",' in ','||" + var2 + "||',')) <> 0";
-        } else if (dataBasyType == DataBaseType.ORACLE) {
-            // instr(',0,100,101,' , ',100,') <> 0
-            return "instr(','||" + var2 + "||',' , '," + var + ",') <> 0";
-        }
-        // find_in_set(100 , '0,100,101')
-        return "find_in_set(" + var + " , " + var2 + ") <> 0";
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java
deleted file mode 100644
index 0e60485..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.common.helper;
-
-import cn.dev33.satoken.context.SaHolder;
-import cn.dev33.satoken.context.model.SaStorage;
-import cn.hutool.core.util.ObjectUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 鏁版嵁鏉冮檺鍔╂墜
- *
- * @author Lion Li
- * @version 3.5.0
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-@SuppressWarnings("unchecked cast")
-public class DataPermissionHelper {
-
-    private static final String DATA_PERMISSION_KEY = "data:permission";
-
-    public static <T> T getVariable(String key) {
-        Map<String, Object> context = getContext();
-        return (T) context.get(key);
-    }
-
-
-    public static void setVariable(String key, Object value) {
-        Map<String, Object> context = getContext();
-        context.put(key, value);
-    }
-
-    public static Map<String, Object> getContext() {
-        SaStorage saStorage = SaHolder.getStorage();
-        Object attribute = saStorage.get(DATA_PERMISSION_KEY);
-        if (ObjectUtil.isNull(attribute)) {
-            saStorage.set(DATA_PERMISSION_KEY, new HashMap<>());
-            attribute = saStorage.get(DATA_PERMISSION_KEY);
-        }
-        if (attribute instanceof Map) {
-            return (Map<String, Object>) attribute;
-        }
-        throw new NullPointerException("data permission context type exception");
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
deleted file mode 100644
index 05e370b..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.ruoyi.common.helper;
-
-import cn.dev33.satoken.context.SaHolder;
-import cn.dev33.satoken.stp.StpUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.enums.DeviceType;
-import com.ruoyi.common.enums.UserType;
-import com.ruoyi.common.exception.UtilException;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-/**
- * 鐧诲綍閴存潈鍔╂墜
- *
- * user_type 涓� 鐢ㄦ埛绫诲瀷 鍚屼竴涓敤鎴疯〃 鍙互鏈夊绉嶇敤鎴风被鍨� 渚嬪 pc,app
- * deivce 涓� 璁惧绫诲瀷 鍚屼竴涓敤鎴风被鍨� 鍙互鏈� 澶氱璁惧绫诲瀷 渚嬪 web,ios
- * 鍙互缁勬垚 鐢ㄦ埛绫诲瀷涓庤澶囩被鍨嬪瀵瑰鐨� 鏉冮檺鐏垫椿鎺у埗
- *
- * 澶氱敤鎴蜂綋绯� 閽堝 澶氱鐢ㄦ埛绫诲瀷 浣嗘潈闄愭帶鍒朵笉涓�鑷�
- * 鍙互缁勬垚 澶氱敤鎴风被鍨嬭〃涓庡璁惧绫诲瀷 鍒嗗埆鎺у埗鏉冮檺
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class LoginHelper {
-
-    public static final String JOIN_CODE = ":";
-    public static final String LOGIN_USER_KEY = "loginUser";
-
-    /**
-     * 鐧诲綍绯荤粺
-     *
-     * @param loginUser 鐧诲綍鐢ㄦ埛淇℃伅
-     */
-    public static void login(LoginUser loginUser) {
-        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
-        StpUtil.login(loginUser.getLoginId());
-        setLoginUser(loginUser);
-    }
-
-    /**
-     * 鐧诲綍绯荤粺 鍩轰簬 璁惧绫诲瀷
-     * 閽堝鐩稿悓鐢ㄦ埛浣撶郴涓嶅悓璁惧
-     *
-     * @param loginUser 鐧诲綍鐢ㄦ埛淇℃伅
-     */
-    public static void loginByDevice(LoginUser loginUser, DeviceType deviceType) {
-        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
-        StpUtil.login(loginUser.getLoginId(), deviceType.getDevice());
-        setLoginUser(loginUser);
-    }
-
-    /**
-     * 璁剧疆鐢ㄦ埛鏁版嵁(澶氱骇缂撳瓨)
-     */
-    public static void setLoginUser(LoginUser loginUser) {
-        StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
-    }
-
-    /**
-     * 鑾峰彇鐢ㄦ埛(澶氱骇缂撳瓨)
-     */
-    public static LoginUser getLoginUser() {
-        LoginUser loginUser = (LoginUser) SaHolder.getStorage().get(LOGIN_USER_KEY);
-        if (loginUser != null) {
-            return loginUser;
-        }
-        loginUser = (LoginUser) StpUtil.getTokenSession().get(LOGIN_USER_KEY);
-        SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser);
-        return loginUser;
-    }
-
-    /**
-     * 鑾峰彇鐢ㄦ埛id
-     */
-    public static Long getUserId() {
-        LoginUser loginUser = getLoginUser();
-        if (ObjectUtil.isNull(loginUser)) {
-            String loginId = StpUtil.getLoginIdAsString();
-            String userId = null;
-            for (UserType value : UserType.values()) {
-                if (StringUtils.contains(loginId, value.getUserType())) {
-                    String[] strs = StringUtils.split(loginId, JOIN_CODE);
-                    // 鐢ㄦ埛id鍦ㄦ�绘槸鍦ㄦ渶鍚�
-                    userId = strs[strs.length - 1];
-                }
-            }
-            if (StringUtils.isBlank(userId)) {
-                throw new UtilException("鐧诲綍鐢ㄦ埛: LoginId寮傚父 => " + loginId);
-            }
-            return Long.parseLong(userId);
-        }
-        return loginUser.getUserId();
-    }
-
-    /**
-     * 鑾峰彇閮ㄩ棬ID
-     */
-    public static Long getDeptId() {
-        return getLoginUser().getDeptId();
-    }
-
-    /**
-     * 鑾峰彇鐢ㄦ埛璐︽埛
-     */
-    public static String getUsername() {
-        return getLoginUser().getUsername();
-    }
-
-    /**
-     * 鑾峰彇鐢ㄦ埛绫诲瀷
-     */
-    public static UserType getUserType() {
-        String loginId = StpUtil.getLoginIdAsString();
-        return UserType.getUserType(loginId);
-    }
-
-    /**
-     * 鏄惁涓虹鐞嗗憳
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 缁撴灉
-     */
-    public static boolean isAdmin(Long userId) {
-        return UserConstants.ADMIN_ID.equals(userId);
-    }
-
-    public static boolean isAdmin() {
-        return isAdmin(getUserId());
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java
deleted file mode 100644
index caa059b..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.ruoyi.common.jackson;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.BeanProperty;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.ContextualSerializer;
-import com.ruoyi.common.annotation.DictDataMapper;
-import com.ruoyi.common.core.service.DictService;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * 瀛楀吀鏁版嵁json搴忓垪鍖栧伐鍏�
- *
- * @author itino
- */
-@Slf4j
-public class DictDataJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
-
-    private String dictType;
-
-    @Override
-    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
-        try {
-            DictService dictService = SpringUtils.getBean(DictService.class);
-            if (ObjectUtil.isNotNull(dictService)) {
-                String label = dictService.getDictLabel(dictType, value);
-                gen.writeString(StringUtils.isNotBlank(label) ? label : value);
-            } else {
-                gen.writeString(value);
-            }
-        } catch (BeansException e) {
-            log.error("瀛楀吀鏁版嵁鏈煡鍒�, 閲囩敤榛樿澶勭悊 => {}", e.getMessage());
-            gen.writeString(value);
-        }
-    }
-
-    @Override
-    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
-        DictDataMapper anno = property.getAnnotation(DictDataMapper.class);
-        if (Objects.nonNull(anno) && StrUtil.isNotBlank(anno.dictType())) {
-            this.dictType = anno.dictType();
-            return this;
-        }
-        return prov.findValueSerializer(property.getType(), property);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/SensitiveJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/SensitiveJsonSerializer.java
deleted file mode 100644
index 41e5781..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/SensitiveJsonSerializer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.ruoyi.common.jackson;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.BeanProperty;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.ser.ContextualSerializer;
-import com.ruoyi.common.annotation.Sensitive;
-import com.ruoyi.common.core.service.SensitiveService;
-import com.ruoyi.common.enums.SensitiveStrategy;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * 鏁版嵁鑴辨晱json搴忓垪鍖栧伐鍏�
- *
- * @author Yjoioooo
- */
-@Slf4j
-public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
-
-    private SensitiveStrategy strategy;
-
-    @Override
-    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
-        try {
-            SensitiveService sensitiveService = SpringUtils.getBean(SensitiveService.class);
-            if (ObjectUtil.isNotNull(sensitiveService) && sensitiveService.isSensitive()) {
-                gen.writeString(strategy.desensitizer().apply(value));
-            } else {
-                gen.writeString(value);
-            }
-        } catch (BeansException e) {
-            log.error("鑴辨晱瀹炵幇涓嶅瓨鍦�, 閲囩敤榛樿澶勭悊 => {}", e.getMessage());
-            gen.writeString(value);
-        }
-    }
-
-    @Override
-    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
-        Sensitive annotation = property.getAnnotation(Sensitive.class);
-        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
-            this.strategy = annotation.strategy();
-            return this;
-        }
-        return prov.findValueSerializer(property.getType(), property);
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java
deleted file mode 100644
index e1bafee..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.SimpleCache;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.ReflectUtil;
-import cn.hutool.core.util.StrUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.springframework.cglib.beans.BeanCopier;
-import org.springframework.cglib.beans.BeanMap;
-import org.springframework.cglib.core.Converter;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * bean娣辨嫹璐濆伐鍏�(鍩轰簬 cglib 鎬ц兘浼樺紓)
- * <p>
- * 閲嶇偣 cglib 涓嶆敮鎸� 鎷疯礉鍒伴摼寮忓璞�
- * 渚嬪: 婧愬璞� 鎷疯礉鍒� 鐩爣(閾惧紡瀵硅薄)
- * 璇峰尯鍒嗗ソ`娴呮嫹璐漙鍜宍娣辨嫹璐漙鍐嶅仛浣跨敤
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class BeanCopyUtils {
-
-    /**
-     * 鍗曞璞″熀浜巆lass鍒涘缓鎷疯礉
-     *
-     * @param source 鏁版嵁鏉ユ簮瀹炰綋
-     * @param desc   鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
-     * @return desc
-     */
-    public static <T, V> V copy(T source, Class<V> desc) {
-        if (ObjectUtil.isNull(source)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(desc)) {
-            return null;
-        }
-        final V target = ReflectUtil.newInstanceIfPossible(desc);
-        return copy(source, target);
-    }
-
-    /**
-     * 鍗曞璞″熀浜庡璞″垱寤烘嫹璐�
-     *
-     * @param source 鏁版嵁鏉ユ簮瀹炰綋
-     * @param desc   杞崲鍚庣殑瀵硅薄
-     * @return desc
-     */
-    public static <T, V> V copy(T source, V desc) {
-        if (ObjectUtil.isNull(source)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(desc)) {
-            return null;
-        }
-        BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null);
-        beanCopier.copy(source, desc, null);
-        return desc;
-    }
-
-    /**
-     * 鍒楄〃瀵硅薄鍩轰簬class鍒涘缓鎷疯礉
-     *
-     * @param sourceList 鏁版嵁鏉ユ簮瀹炰綋鍒楄〃
-     * @param desc       鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
-     * @return desc
-     */
-    public static <T, V> List<V> copyList(List<T> sourceList, Class<V> desc) {
-        if (ObjectUtil.isNull(sourceList)) {
-            return null;
-        }
-        if (CollUtil.isEmpty(sourceList)) {
-            return CollUtil.newArrayList();
-        }
-        return StreamUtils.toList(sourceList, source -> {
-            V target = ReflectUtil.newInstanceIfPossible(desc);
-            copy(source, target);
-            return target;
-        });
-    }
-
-    /**
-     * bean鎷疯礉鍒癿ap
-     *
-     * @param bean 鏁版嵁鏉ユ簮瀹炰綋
-     * @return map瀵硅薄
-     */
-    @SuppressWarnings("unchecked")
-    public static <T> Map<String, Object> copyToMap(T bean) {
-        if (ObjectUtil.isNull(bean)) {
-            return null;
-        }
-        return BeanMap.create(bean);
-    }
-
-    /**
-     * map鎷疯礉鍒癰ean
-     *
-     * @param map       鏁版嵁鏉ユ簮
-     * @param beanClass bean绫�
-     * @return bean瀵硅薄
-     */
-    public static <T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
-        if (MapUtil.isEmpty(map)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(beanClass)) {
-            return null;
-        }
-        T bean = ReflectUtil.newInstanceIfPossible(beanClass);
-        return mapToBean(map, bean);
-    }
-
-    /**
-     * map鎷疯礉鍒癰ean
-     *
-     * @param map  鏁版嵁鏉ユ簮
-     * @param bean bean瀵硅薄
-     * @return bean瀵硅薄
-     */
-    public static <T> T mapToBean(Map<String, Object> map, T bean) {
-        if (MapUtil.isEmpty(map)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(bean)) {
-            return null;
-        }
-        BeanMap.create(bean).putAll(map);
-        return bean;
-    }
-
-    /**
-     * map鎷疯礉鍒癿ap
-     *
-     * @param map   鏁版嵁鏉ユ簮
-     * @param clazz 杩斿洖鐨勫璞$被鍨�
-     * @return map瀵硅薄
-     */
-    public static <T, V> Map<String, V> mapToMap(Map<String, T> map, Class<V> clazz) {
-        if (MapUtil.isEmpty(map)) {
-            return null;
-        }
-        if (ObjectUtil.isNull(clazz)) {
-            return null;
-        }
-        Map<String, V> copyMap = new LinkedHashMap<>(map.size());
-        map.forEach((k, v) -> copyMap.put(k, copy(v, clazz)));
-        return copyMap;
-    }
-
-    /**
-     * BeanCopier灞炴�х紦瀛�<br>
-     * 缂撳瓨鐢ㄤ簬闃叉澶氭鍙嶅皠閫犳垚鐨勬�ц兘闂
-     *
-     * @author Looly
-     * @since 5.4.1
-     */
-    public enum BeanCopierCache {
-        /**
-         * BeanCopier灞炴�х紦瀛樺崟渚�
-         */
-        INSTANCE;
-
-        private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
-
-        /**
-         * 鑾峰緱绫讳笌杞崲鍣ㄧ敓鎴愮殑key鍦▄@link BeanCopier}鐨凪ap涓搴旂殑鍏冪礌
-         *
-         * @param srcClass    婧怋ean鐨勭被
-         * @param targetClass 鐩爣Bean鐨勭被
-         * @param converter   杞崲鍣�
-         * @return Map涓搴旂殑BeanCopier
-         */
-        public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Converter converter) {
-            final String key = genKey(srcClass, targetClass, converter);
-            return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null));
-        }
-
-        /**
-         * 鑾峰緱绫讳笌杞崲鍣ㄧ敓鎴愮殑key
-         *
-         * @param srcClass    婧怋ean鐨勭被
-         * @param targetClass 鐩爣Bean鐨勭被
-         * @param converter   杞崲鍣�
-         * @return 灞炴�у悕鍜孧ap鏄犲皠鐨刱ey
-         */
-        private String genKey(Class<?> srcClass, Class<?> targetClass, Converter converter) {
-            final StringBuilder key = StrUtil.builder()
-                .append(srcClass.getName()).append('#').append(targetClass.getName());
-            if (null != converter) {
-                key.append('#').append(converter.getClass().getName());
-            }
-            return key.toString();
-        }
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
deleted file mode 100644
index c64f1f8..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.ruoyi.common.utils;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.commons.lang3.time.DateFormatUtils;
-
-import java.lang.management.ManagementFactory;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.Date;
-
-/**
- * 鏃堕棿宸ュ叿绫�
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
-
-    public static final String YYYY = "yyyy";
-
-    public static final String YYYY_MM = "yyyy-MM";
-
-    public static final String YYYY_MM_DD = "yyyy-MM-dd";
-
-    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
-
-    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
-
-    private static final String[] PARSE_PATTERNS = {
-        "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
-        "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
-        "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
-
-    /**
-     * 鑾峰彇褰撳墠Date鍨嬫棩鏈�
-     *
-     * @return Date() 褰撳墠鏃ユ湡
-     */
-    public static Date getNowDate() {
-        return new Date();
-    }
-
-    /**
-     * 鑾峰彇褰撳墠鏃ユ湡, 榛樿鏍煎紡涓簓yyy-MM-dd
-     *
-     * @return String
-     */
-    public static String getDate() {
-        return dateTimeNow(YYYY_MM_DD);
-    }
-
-    public static String getTime() {
-        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
-    }
-
-    public static String dateTimeNow() {
-        return dateTimeNow(YYYYMMDDHHMMSS);
-    }
-
-    public static String dateTimeNow(final String format) {
-        return parseDateToStr(format, new Date());
-    }
-
-    public static String dateTime(final Date date) {
-        return parseDateToStr(YYYY_MM_DD, date);
-    }
-
-    public static String parseDateToStr(final String format, final Date date) {
-        return new SimpleDateFormat(format).format(date);
-    }
-
-    public static Date dateTime(final String format, final String ts) {
-        try {
-            return new SimpleDateFormat(format).parse(ts);
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�2018/08/08
-     */
-    public static String datePath() {
-        Date now = new Date();
-        return DateFormatUtils.format(now, "yyyy/MM/dd");
-    }
-
-    /**
-     * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�20180808
-     */
-    public static String dateTime() {
-        Date now = new Date();
-        return DateFormatUtils.format(now, "yyyyMMdd");
-    }
-
-    /**
-     * 鏃ユ湡鍨嬪瓧绗︿覆杞寲涓烘棩鏈� 鏍煎紡
-     */
-    public static Date parseDate(Object str) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            return parseDate(str.toString(), PARSE_PATTERNS);
-        } catch (ParseException e) {
-            return null;
-        }
-    }
-
-    /**
-     * 鑾峰彇鏈嶅姟鍣ㄥ惎鍔ㄦ椂闂�
-     */
-    public static Date getServerStartDate() {
-        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
-        return new Date(time);
-    }
-
-    /**
-     * 璁$畻鐩稿樊澶╂暟
-     */
-    public static int differentDaysByMillisecond(Date date1, Date date2) {
-        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
-    }
-
-    /**
-     * 璁$畻涓や釜鏃堕棿宸�
-     */
-    public static String getDatePoor(Date endDate, Date nowDate) {
-        long nd = 1000 * 24 * 60 * 60;
-        long nh = 1000 * 60 * 60;
-        long nm = 1000 * 60;
-        // long ns = 1000;
-        // 鑾峰緱涓や釜鏃堕棿鐨勬绉掓椂闂村樊寮�
-        long diff = endDate.getTime() - nowDate.getTime();
-        // 璁$畻宸灏戝ぉ
-        long day = diff / nd;
-        // 璁$畻宸灏戝皬鏃�
-        long hour = diff % nd / nh;
-        // 璁$畻宸灏戝垎閽�
-        long min = diff % nd % nh / nm;
-        // 璁$畻宸灏戠//杈撳嚭缁撴灉
-        // long sec = diff % nd % nh % nm / ns;
-        return day + "澶�" + hour + "灏忔椂" + min + "鍒嗛挓";
-    }
-
-    /**
-     * 澧炲姞 LocalDateTime ==> Date
-     */
-    public static Date toDate(LocalDateTime temporalAccessor) {
-        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
-        return Date.from(zdt.toInstant());
-    }
-
-    /**
-     * 澧炲姞 LocalDate ==> Date
-     */
-    public static Date toDate(LocalDate temporalAccessor) {
-        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
-        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
-        return Date.from(zdt.toInstant());
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java
deleted file mode 100644
index e5c471e..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.lang.Dict;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.exc.MismatchedInputException;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * JSON 宸ュ叿绫�
- *
- * @author 鑺嬮亾婧愮爜
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class JsonUtils {
-
-    private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class);
-
-    public static ObjectMapper getObjectMapper() {
-        return OBJECT_MAPPER;
-    }
-
-    public static String toJsonString(Object object) {
-        if (ObjectUtil.isNull(object)) {
-            return null;
-        }
-        try {
-            return OBJECT_MAPPER.writeValueAsString(object);
-        } catch (JsonProcessingException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> T parseObject(String text, Class<T> clazz) {
-        if (StringUtils.isEmpty(text)) {
-            return null;
-        }
-        try {
-            return OBJECT_MAPPER.readValue(text, clazz);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
-        if (ArrayUtil.isEmpty(bytes)) {
-            return null;
-        }
-        try {
-            return OBJECT_MAPPER.readValue(bytes, clazz);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> T parseObject(String text, TypeReference<T> typeReference) {
-        if (StringUtils.isBlank(text)) {
-            return null;
-        }
-        try {
-            return OBJECT_MAPPER.readValue(text, typeReference);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static Dict parseMap(String text) {
-        if (StringUtils.isBlank(text)) {
-            return null;
-        }
-        try {
-            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class));
-        } catch (MismatchedInputException e) {
-            // 绫诲瀷涓嶅尮閰嶈鏄庝笉鏄痡son
-            return null;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static List<Dict> parseArrayMap(String text) {
-        if (StringUtils.isBlank(text)) {
-            return null;
-        }
-        try {
-            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Dict.class));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static <T> List<T> parseArray(String text, Class<T> clazz) {
-        if (StringUtils.isEmpty(text)) {
-            return new ArrayList<>();
-        }
-        try {
-            return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
deleted file mode 100644
index c9c091d..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.common.utils;
-
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.springframework.context.MessageSource;
-import org.springframework.context.i18n.LocaleContextHolder;
-
-/**
- * 鑾峰彇i18n璧勬簮鏂囦欢
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class MessageUtils {
-
-    private static final MessageSource MESSAGE_SOURCE = SpringUtils.getBean(MessageSource.class);
-
-    /**
-     * 鏍规嵁娑堟伅閿拰鍙傛暟 鑾峰彇娑堟伅 濮旀墭缁檚pring messageSource
-     *
-     * @param code 娑堟伅閿�
-     * @param args 鍙傛暟
-     * @return 鑾峰彇鍥介檯鍖栫炕璇戝��
-     */
-    public static String message(String code, Object... args) {
-        return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
deleted file mode 100644
index fd57842..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.convert.Convert;
-import cn.hutool.extra.servlet.JakartaServletUtil;
-import cn.hutool.http.HttpStatus;
-import com.ruoyi.common.constant.Constants;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-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 java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 瀹㈡埛绔伐鍏风被
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ServletUtils extends JakartaServletUtil {
-
-    /**
-     * 鑾峰彇String鍙傛暟
-     */
-    public static String getParameter(String name) {
-        return getRequest().getParameter(name);
-    }
-
-    /**
-     * 鑾峰彇String鍙傛暟
-     */
-    public static String getParameter(String name, String defaultValue) {
-        return Convert.toStr(getRequest().getParameter(name), defaultValue);
-    }
-
-    /**
-     * 鑾峰彇Integer鍙傛暟
-     */
-    public static Integer getParameterToInt(String name) {
-        return Convert.toInt(getRequest().getParameter(name));
-    }
-
-    /**
-     * 鑾峰彇Integer鍙傛暟
-     */
-    public static Integer getParameterToInt(String name, Integer defaultValue) {
-        return Convert.toInt(getRequest().getParameter(name), defaultValue);
-    }
-
-    /**
-     * 鑾峰彇Boolean鍙傛暟
-     */
-    public static Boolean getParameterToBool(String name) {
-        return Convert.toBool(getRequest().getParameter(name));
-    }
-
-    /**
-     * 鑾峰彇Boolean鍙傛暟
-     */
-    public static Boolean getParameterToBool(String name, Boolean defaultValue) {
-        return Convert.toBool(getRequest().getParameter(name), defaultValue);
-    }
-
-    /**
-     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
-     *
-     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
-     * @return Map
-     */
-    public static Map<String, String[]> getParams(ServletRequest request) {
-        final Map<String, String[]> map = request.getParameterMap();
-        return Collections.unmodifiableMap(map);
-    }
-
-    /**
-     * 鑾峰緱鎵�鏈夎姹傚弬鏁�
-     *
-     * @param request 璇锋眰瀵硅薄{@link ServletRequest}
-     * @return Map
-     */
-    public static Map<String, String> getParamMap(ServletRequest request) {
-        Map<String, String> params = new HashMap<>();
-        for (Map.Entry<String, String[]> entry : getParams(request).entrySet()) {
-            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
-        }
-        return params;
-    }
-
-    /**
-     * 鑾峰彇request
-     */
-    public static HttpServletRequest getRequest() {
-        return getRequestAttributes().getRequest();
-    }
-
-    /**
-     * 鑾峰彇response
-     */
-    public static HttpServletResponse getResponse() {
-        return getRequestAttributes().getResponse();
-    }
-
-    /**
-     * 鑾峰彇session
-     */
-    public static HttpSession getSession() {
-        return getRequest().getSession();
-    }
-
-    public static ServletRequestAttributes getRequestAttributes() {
-        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
-        return (ServletRequestAttributes) attributes;
-    }
-
-    /**
-     * 灏嗗瓧绗︿覆娓叉煋鍒板鎴风
-     *
-     * @param response 娓叉煋瀵硅薄
-     * @param string   寰呮覆鏌撶殑瀛楃涓�
-     */
-    public static void renderString(HttpServletResponse response, String string) {
-        try {
-            response.setStatus(HttpStatus.HTTP_OK);
-            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
-            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
-            response.getWriter().print(string);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * 鏄惁鏄疉jax寮傛璇锋眰
-     *
-     * @param request
-     */
-    public static boolean isAjaxRequest(HttpServletRequest request) {
-
-        String accept = request.getHeader("accept");
-        if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) {
-            return true;
-        }
-
-        String xRequestedWith = request.getHeader("X-Requested-With");
-        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) {
-            return true;
-        }
-
-        String uri = request.getRequestURI();
-        if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) {
-            return true;
-        }
-
-        String ajax = request.getParameter("__ajax");
-        return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml");
-    }
-
-    public static String getClientIP() {
-        return getClientIP(getRequest());
-    }
-
-    /**
-     * 鍐呭缂栫爜
-     *
-     * @param str 鍐呭
-     * @return 缂栫爜鍚庣殑鍐呭
-     */
-    public static String urlEncode(String str) {
-        try {
-            return URLEncoder.encode(str, Constants.UTF8);
-        } catch (UnsupportedEncodingException e) {
-            return StringUtils.EMPTY;
-        }
-    }
-
-    /**
-     * 鍐呭瑙g爜
-     *
-     * @param str 鍐呭
-     * @return 瑙g爜鍚庣殑鍐呭
-     */
-    public static String urlDecode(String str) {
-        try {
-            return URLDecoder.decode(str, Constants.UTF8);
-        } catch (UnsupportedEncodingException e) {
-            return StringUtils.EMPTY;
-        }
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java
deleted file mode 100644
index fccd9e3..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.*;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * stream 娴佸伐鍏风被
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class StreamUtils {
-
-    /**
-     * 灏哻ollection杩囨护
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param function   杩囨护鏂规硶
-     * @return 杩囨护鍚庣殑list
-     */
-    public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) {
-        if (CollUtil.isEmpty(collection)) {
-            return CollUtil.newArrayList();
-        }
-        return collection.stream().filter(function).collect(Collectors.toList());
-    }
-
-    /**
-     * 灏哻ollection鎷兼帴
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param function   鎷兼帴鏂规硶
-     * @return 鎷兼帴鍚庣殑list
-     */
-    public static <E> String join(Collection<E> collection, Function<E, String> function) {
-        return join(collection, function, ",");
-    }
-
-    /**
-     * 灏哻ollection鎷兼帴
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param function   鎷兼帴鏂规硶
-     * @param delimiter  鎷兼帴绗�
-     * @return 鎷兼帴鍚庣殑list
-     */
-    public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) {
-        if (CollUtil.isEmpty(collection)) {
-            return StringUtils.EMPTY;
-        }
-        return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
-    }
-
-    /**
-     * 灏哻ollection鎺掑簭
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param comparing  鎺掑簭鏂规硶
-     * @return 鎺掑簭鍚庣殑list
-     */
-    public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) {
-        if (CollUtil.isEmpty(collection)) {
-            return CollUtil.newArrayList();
-        }
-        return collection.stream().sorted(comparing).collect(Collectors.toList());
-    }
-
-    /**
-     * 灏哻ollection杞寲涓虹被鍨嬩笉鍙樼殑map<br>
-     * <B>{@code Collection<V>  ---->  Map<K,V>}</B>
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param key        V绫诲瀷杞寲涓篕绫诲瀷鐨刲ambda鏂规硶
-     * @param <V>        collection涓殑娉涘瀷
-     * @param <K>        map涓殑key绫诲瀷
-     * @return 杞寲鍚庣殑map
-     */
-    public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
-    }
-
-    /**
-     * 灏咰ollection杞寲涓簃ap(value绫诲瀷涓巆ollection鐨勬硾鍨嬩笉鍚�)<br>
-     * <B>{@code Collection<E> -----> Map<K,V>  }</B>
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param key        E绫诲瀷杞寲涓篕绫诲瀷鐨刲ambda鏂规硶
-     * @param value      E绫诲瀷杞寲涓篤绫诲瀷鐨刲ambda鏂规硶
-     * @param <E>        collection涓殑娉涘瀷
-     * @param <K>        map涓殑key绫诲瀷
-     * @param <V>        map涓殑value绫诲瀷
-     * @return 杞寲鍚庣殑map
-     */
-    public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
-    }
-
-    /**
-     * 灏哻ollection鎸夌収瑙勫垯(姣斿鏈夌浉鍚岀殑鐝骇id)鍒嗙被鎴恗ap<br>
-     * <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
-     *
-     * @param collection 闇�瑕佸垎绫荤殑闆嗗悎
-     * @param key        鍒嗙被鐨勮鍒�
-     * @param <E>        collection涓殑娉涘瀷
-     * @param <K>        map涓殑key绫诲瀷
-     * @return 鍒嗙被鍚庣殑map
-     */
-    public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection
-            .stream()
-            .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
-    }
-
-    /**
-     * 灏哻ollection鎸夌収涓や釜瑙勫垯(姣斿鏈夌浉鍚岀殑骞寸骇id,鐝骇id)鍒嗙被鎴愬弻灞俶ap<br>
-     * <B>{@code Collection<E>  --->  Map<T,Map<U,List<E>>> } </B>
-     *
-     * @param collection 闇�瑕佸垎绫荤殑闆嗗悎
-     * @param key1       绗竴涓垎绫荤殑瑙勫垯
-     * @param key2       绗簩涓垎绫荤殑瑙勫垯
-     * @param <E>        闆嗗悎鍏冪礌绫诲瀷
-     * @param <K>        绗竴涓猰ap涓殑key绫诲瀷
-     * @param <U>        绗簩涓猰ap涓殑key绫诲瀷
-     * @return 鍒嗙被鍚庣殑map
-     */
-    public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) {
-        if (CollUtil.isEmpty(collection)) {
-            return MapUtil.newHashMap();
-        }
-        return collection
-            .stream()
-            .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
-    }
-
-    /**
-     * 灏哻ollection鎸夌収涓や釜瑙勫垯(姣斿鏈夌浉鍚岀殑骞寸骇id,鐝骇id)鍒嗙被鎴愬弻灞俶ap<br>
-     * <B>{@code Collection<E>  --->  Map<T,Map<U,E>> } </B>
-     *
-     * @param collection 闇�瑕佸垎绫荤殑闆嗗悎
-     * @param key1       绗竴涓垎绫荤殑瑙勫垯
-     * @param key2       绗簩涓垎绫荤殑瑙勫垯
-     * @param <T>        绗竴涓猰ap涓殑key绫诲瀷
-     * @param <U>        绗簩涓猰ap涓殑key绫诲瀷
-     * @param <E>        collection涓殑娉涘瀷
-     * @return 鍒嗙被鍚庣殑map
-     */
-    public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) {
-        if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
-            return MapUtil.newHashMap();
-        }
-        return collection
-            .stream()
-            .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
-    }
-
-    /**
-     * 灏哻ollection杞寲涓篖ist闆嗗悎锛屼絾鏄袱鑰呯殑娉涘瀷涓嶅悓<br>
-     * <B>{@code Collection<E>  ------>  List<T> } </B>
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param function   collection涓殑娉涘瀷杞寲涓簂ist娉涘瀷鐨刲ambda琛ㄨ揪寮�
-     * @param <E>        collection涓殑娉涘瀷
-     * @param <T>        List涓殑娉涘瀷
-     * @return 杞寲鍚庣殑list
-     */
-    public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
-        if (CollUtil.isEmpty(collection)) {
-            return CollUtil.newArrayList();
-        }
-        return collection
-            .stream()
-            .map(function)
-            .filter(Objects::nonNull)
-            .collect(Collectors.toList());
-    }
-
-    /**
-     * 灏哻ollection杞寲涓篠et闆嗗悎锛屼絾鏄袱鑰呯殑娉涘瀷涓嶅悓<br>
-     * <B>{@code Collection<E>  ------>  Set<T> } </B>
-     *
-     * @param collection 闇�瑕佽浆鍖栫殑闆嗗悎
-     * @param function   collection涓殑娉涘瀷杞寲涓簊et娉涘瀷鐨刲ambda琛ㄨ揪寮�
-     * @param <E>        collection涓殑娉涘瀷
-     * @param <T>        Set涓殑娉涘瀷
-     * @return 杞寲鍚庣殑Set
-     */
-    public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
-        if (CollUtil.isEmpty(collection) || function == null) {
-            return CollUtil.newHashSet();
-        }
-        return collection
-            .stream()
-            .map(function)
-            .filter(Objects::nonNull)
-            .collect(Collectors.toSet());
-    }
-
-
-    /**
-     * 鍚堝苟涓や釜鐩稿悓key绫诲瀷鐨刴ap
-     *
-     * @param map1  绗竴涓渶瑕佸悎骞剁殑 map
-     * @param map2  绗簩涓渶瑕佸悎骞剁殑 map
-     * @param merge 鍚堝苟鐨刲ambda锛屽皢key  value1 value2鍚堝苟鎴愭渶缁堢殑绫诲瀷,娉ㄦ剰value鍙兘涓虹┖鐨勬儏鍐�
-     * @param <K>   map涓殑key绫诲瀷
-     * @param <X>   绗竴涓� map鐨剉alue绫诲瀷
-     * @param <Y>   绗簩涓� map鐨剉alue绫诲瀷
-     * @param <V>   鏈�缁坢ap鐨剉alue绫诲瀷
-     * @return 鍚堝苟鍚庣殑map
-     */
-    public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) {
-        if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) {
-            return MapUtil.newHashMap();
-        } else if (MapUtil.isEmpty(map1)) {
-            map1 = MapUtil.newHashMap();
-        } else if (MapUtil.isEmpty(map2)) {
-            map2 = MapUtil.newHashMap();
-        }
-        Set<K> key = new HashSet<>();
-        key.addAll(map1.keySet());
-        key.addAll(map2.keySet());
-        Map<K, V> map = new HashMap<>();
-        for (K t : key) {
-            X x = map1.get(t);
-            Y y = map2.get(t);
-            V z = merge.apply(x, y);
-            if (z != null) {
-                map.put(t, z);
-            }
-        }
-        return map;
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
deleted file mode 100644
index 16f8861..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
+++ /dev/null
@@ -1,273 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Validator;
-import cn.hutool.core.util.StrUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.springframework.util.AntPathMatcher;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * 瀛楃涓插伐鍏风被
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class StringUtils extends org.apache.commons.lang3.StringUtils {
-
-    /**
-     * 鑾峰彇鍙傛暟涓嶄负绌哄��
-     *
-     * @param str defaultValue 瑕佸垽鏂殑value
-     * @return value 杩斿洖鍊�
-     */
-    public static String blankToDefault(String str, String defaultValue) {
-        return StrUtil.blankToDefault(str, defaultValue);
-    }
-
-    /**
-     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓虹┖涓�
-     *
-     * @param str String
-     * @return true锛氫负绌� false锛氶潪绌�
-     */
-    public static boolean isEmpty(String str) {
-        return StrUtil.isEmpty(str);
-    }
-
-    /**
-     * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓洪潪绌轰覆
-     *
-     * @param str String
-     * @return true锛氶潪绌轰覆 false锛氱┖涓�
-     */
-    public static boolean isNotEmpty(String str) {
-        return !isEmpty(str);
-    }
-
-    /**
-     * 鍘荤┖鏍�
-     */
-    public static String trim(String str) {
-        return StrUtil.trim(str);
-    }
-
-    /**
-     * 鎴彇瀛楃涓�
-     *
-     * @param str   瀛楃涓�
-     * @param start 寮�濮�
-     * @return 缁撴灉
-     */
-    public static String substring(final String str, int start) {
-        return substring(str, start, str.length());
-    }
-
-    /**
-     * 鎴彇瀛楃涓�
-     *
-     * @param str   瀛楃涓�
-     * @param start 寮�濮�
-     * @param end   缁撴潫
-     * @return 缁撴灉
-     */
-    public static String substring(final String str, int start, int end) {
-        return StrUtil.sub(str, start, end);
-    }
-
-    /**
-     * 鏍煎紡鍖栨枃鏈�, {} 琛ㄧず鍗犱綅绗�<br>
-     * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
-     * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
-     * 渚嬶細<br>
-     * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
-     * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is {} for a<br>
-     * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
-     *
-     * @param template 鏂囨湰妯℃澘锛岃鏇挎崲鐨勯儴鍒嗙敤 {} 琛ㄧず
-     * @param params   鍙傛暟鍊�
-     * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
-     */
-    public static String format(String template, Object... params) {
-        return StrUtil.format(template, params);
-    }
-
-    /**
-     * 鏄惁涓篽ttp(s)://寮�澶�
-     *
-     * @param link 閾炬帴
-     * @return 缁撴灉
-     */
-    public static boolean ishttp(String link) {
-        return Validator.isUrl(link);
-    }
-
-    /**
-     * 瀛楃涓茶浆set
-     *
-     * @param str 瀛楃涓�
-     * @param sep 鍒嗛殧绗�
-     * @return set闆嗗悎
-     */
-    public static Set<String> str2Set(String str, String sep) {
-        return new HashSet<>(str2List(str, sep, true, false));
-    }
-
-    /**
-     * 瀛楃涓茶浆list
-     *
-     * @param str         瀛楃涓�
-     * @param sep         鍒嗛殧绗�
-     * @param filterBlank 杩囨护绾┖鐧�
-     * @param trim        鍘绘帀棣栧熬绌虹櫧
-     * @return list闆嗗悎
-     */
-    public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
-        List<String> list = new ArrayList<>();
-        if (isEmpty(str)) {
-            return list;
-        }
-
-        // 杩囨护绌虹櫧瀛楃涓�
-        if (filterBlank && isBlank(str)) {
-            return list;
-        }
-        String[] split = str.split(sep);
-        for (String string : split) {
-            if (filterBlank && isBlank(string)) {
-                continue;
-            }
-            if (trim) {
-                string = trim(string);
-            }
-            list.add(string);
-        }
-
-        return list;
-    }
-
-    /**
-     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆鍚屾椂涓插拷鐣ュぇ灏忓啓
-     *
-     * @param cs                  鎸囧畾瀛楃涓�
-     * @param searchCharSequences 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
-     * @return 鏄惁鍖呭惈浠绘剰涓�涓瓧绗︿覆
-     */
-    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
-        return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences);
-    }
-
-    /**
-     * 椹煎嘲杞笅鍒掔嚎鍛藉悕
-     */
-    public static String toUnderScoreCase(String str) {
-        return StrUtil.toUnderlineCase(str);
-    }
-
-    /**
-     * 鏄惁鍖呭惈瀛楃涓�
-     *
-     * @param str  楠岃瘉瀛楃涓�
-     * @param strs 瀛楃涓茬粍
-     * @return 鍖呭惈杩斿洖true
-     */
-    public static boolean inStringIgnoreCase(String str, String... strs) {
-        return StrUtil.equalsAnyIgnoreCase(str, strs);
-    }
-
-    /**
-     * 灏嗕笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆杞崲涓洪┘宄板紡銆傚鏋滆浆鎹㈠墠鐨勪笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆涓虹┖锛屽垯杩斿洖绌哄瓧绗︿覆銆� 渚嬪锛欻ELLO_WORLD->HelloWorld
-     *
-     * @param name 杞崲鍓嶇殑涓嬪垝绾垮ぇ鍐欐柟寮忓懡鍚嶇殑瀛楃涓�
-     * @return 杞崲鍚庣殑椹煎嘲寮忓懡鍚嶇殑瀛楃涓�
-     */
-    public static String convertToCamelCase(String name) {
-        return StrUtil.upperFirst(StrUtil.toCamelCase(name));
-    }
-
-    /**
-     * 椹煎嘲寮忓懡鍚嶆硶 渚嬪锛歶ser_name->userName
-     */
-    public static String toCamelCase(String s) {
-        return StrUtil.toCamelCase(s);
-    }
-
-    /**
-     * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀尮閰嶆寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆
-     *
-     * @param str  鎸囧畾瀛楃涓�
-     * @param strs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
-     * @return 鏄惁鍖归厤
-     */
-    public static boolean matches(String str, List<String> strs) {
-        if (isEmpty(str) || CollUtil.isEmpty(strs)) {
-            return false;
-        }
-        for (String pattern : strs) {
-            if (isMatch(pattern, str)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 鍒ゆ柇url鏄惁涓庤鍒欓厤缃�:
-     * ? 琛ㄧず鍗曚釜瀛楃;
-     * * 琛ㄧず涓�灞傝矾寰勫唴鐨勪换鎰忓瓧绗︿覆锛屼笉鍙法灞傜骇;
-     * ** 琛ㄧず浠绘剰灞傝矾寰�;
-     *
-     * @param pattern 鍖归厤瑙勫垯
-     * @param url     闇�瑕佸尮閰嶇殑url
-     * @return
-     */
-    public static boolean isMatch(String pattern, String url) {
-        AntPathMatcher matcher = new AntPathMatcher();
-        return matcher.match(pattern, url);
-    }
-
-    /**
-     * 鏁板瓧宸﹁竟琛ラ綈0锛屼娇涔嬭揪鍒版寚瀹氶暱搴︺�傛敞鎰忥紝濡傛灉鏁板瓧杞崲涓哄瓧绗︿覆鍚庯紝闀垮害澶т簬size锛屽垯鍙繚鐣� 鏈�鍚巗ize涓瓧绗︺��
-     *
-     * @param num 鏁板瓧瀵硅薄
-     * @param size 瀛楃涓叉寚瀹氶暱搴�
-     * @return 杩斿洖鏁板瓧鐨勫瓧绗︿覆鏍煎紡锛岃瀛楃涓蹭负鎸囧畾闀垮害銆�
-     */
-    public static final String padl(final Number num, final int size) {
-        return padl(num.toString(), size, '0');
-    }
-
-    /**
-     * 瀛楃涓插乏琛ラ綈銆傚鏋滃師濮嬪瓧绗︿覆s闀垮害澶т簬size锛屽垯鍙繚鐣欐渶鍚巗ize涓瓧绗︺��
-     *
-     * @param s 鍘熷瀛楃涓�
-     * @param size 瀛楃涓叉寚瀹氶暱搴�
-     * @param c 鐢ㄤ簬琛ラ綈鐨勫瓧绗�
-     * @return 杩斿洖鎸囧畾闀垮害鐨勫瓧绗︿覆锛岀敱鍘熷瓧绗︿覆宸﹁ˉ榻愭垨鎴彇寰楀埌銆�
-     */
-    public static final String padl(final String s, final int size, final char c) {
-        final StringBuilder sb = new StringBuilder(size);
-        if (s != null) {
-            final int len = s.length();
-            if (s.length() <= size) {
-                for (int i = size - len; i > 0; i--) {
-                    sb.append(c);
-                }
-                sb.append(s);
-            } else {
-                return s.substring(len - size, len);
-            }
-        } else {
-            for (int i = size; i > 0; i--) {
-                sb.append(c);
-            }
-        }
-        return sb.toString();
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
deleted file mode 100644
index 1952929..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.ruoyi.common.utils;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.concurrent.*;
-
-/**
- * 绾跨▼鐩稿叧宸ュ叿绫�.
- *
- * @author ruoyi
- */
-@Slf4j
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class Threads {
-
-    /**
-     * sleep绛夊緟,鍗曚綅涓烘绉�
-     */
-    public static void sleep(long milliseconds) {
-        try {
-            Thread.sleep(milliseconds);
-        } catch (InterruptedException e) {
-            return;
-        }
-    }
-
-    /**
-     * 鍋滄绾跨▼姹�
-     * 鍏堜娇鐢╯hutdown, 鍋滄鎺ユ敹鏂颁换鍔″苟灏濊瘯瀹屾垚鎵�鏈夊凡瀛樺湪浠诲姟.
-     * 濡傛灉瓒呮椂, 鍒欒皟鐢╯hutdownNow, 鍙栨秷鍦╳orkQueue涓璓ending鐨勪换鍔�,骞朵腑鏂墍鏈夐樆濉炲嚱鏁�.
-     * 濡傛灉浠嶇劧瓒呮檪锛屽墖寮峰埗閫�鍑�.
-     * 鍙﹀鍦╯hutdown鏃剁嚎绋嬫湰韬璋冪敤涓柇鍋氫簡澶勭悊.
-     */
-    public static void shutdownAndAwaitTermination(ExecutorService pool) {
-        if (pool != null && !pool.isShutdown()) {
-            pool.shutdown();
-            try {
-                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
-                    pool.shutdownNow();
-                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
-                        log.info("Pool did not terminate");
-                    }
-                }
-            } catch (InterruptedException ie) {
-                pool.shutdownNow();
-                Thread.currentThread().interrupt();
-            }
-        }
-    }
-
-    /**
-     * 鎵撳嵃绾跨▼寮傚父淇℃伅
-     */
-    public static void printException(Runnable r, Throwable t) {
-        if (t == null && r instanceof Future<?>) {
-            try {
-                Future<?> future = (Future<?>) r;
-                if (future.isDone()) {
-                    future.get();
-                }
-            } catch (CancellationException ce) {
-                t = ce;
-            } catch (ExecutionException ee) {
-                t = ee.getCause();
-            } catch (InterruptedException ie) {
-                Thread.currentThread().interrupt();
-            }
-        }
-        if (t != null) {
-            log.error(t.getMessage(), t);
-        }
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeBuildUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeBuildUtils.java
deleted file mode 100644
index f9f8fa1..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeBuildUtils.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.tree.Tree;
-import cn.hutool.core.lang.tree.TreeNodeConfig;
-import cn.hutool.core.lang.tree.TreeUtil;
-import cn.hutool.core.lang.tree.parser.NodeParser;
-import com.ruoyi.common.utils.reflect.ReflectUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-/**
- * 鎵╁睍 hutool TreeUtil 灏佽绯荤粺鏍戞瀯寤�
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class TreeBuildUtils extends TreeUtil {
-
-    /**
-     * 鏍规嵁鍓嶇瀹氬埗宸紓鍖栧瓧娈�
-     */
-    public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
-
-    public static <T, K> List<Tree<K>> build(List<T> list, NodeParser<T, K> nodeParser) {
-        if (CollUtil.isEmpty(list)) {
-            return null;
-        }
-        K k = ReflectUtils.invokeGetter(list.get(0), "parentId");
-        return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser);
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ValidatorUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ValidatorUtils.java
deleted file mode 100644
index c13cbe3..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ValidatorUtils.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.ruoyi.common.utils;
-
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ConstraintViolationException;
-import jakarta.validation.Validator;
-import java.util.Set;
-
-/**
- * Validator 鏍¢獙妗嗘灦宸ュ叿
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ValidatorUtils {
-
-    private static final Validator VALID = SpringUtils.getBean(Validator.class);
-
-    public static <T> void validate(T object, Class<?>... groups) {
-        Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
-        if (!validate.isEmpty()) {
-            throw new ConstraintViolationException("鍙傛暟鏍¢獙寮傚父", validate);
-        }
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java
deleted file mode 100644
index a3ed32d..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/MailUtils.java
+++ /dev/null
@@ -1,468 +0,0 @@
-package com.ruoyi.common.utils.email;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.CharUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.extra.mail.*;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import jakarta.mail.Authenticator;
-import jakarta.mail.Session;
-import java.io.File;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-
-/**
- * 閭欢宸ュ叿绫�
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class MailUtils {
-
-    private static final MailAccount ACCOUNT = SpringUtils.getBean(MailAccount.class);
-
-    /**
-     * 鑾峰彇閭欢鍙戦�佸疄渚�
-     */
-    public static MailAccount getMailAccount() {
-        return ACCOUNT;
-    }
-
-    /**
-     * 鑾峰彇閭欢鍙戦�佸疄渚� (鑷畾涔夊彂閫佷汉浠ュ強鎺堟潈鐮�)
-     *
-     * @param user 鍙戦�佷汉
-     * @param pass 鎺堟潈鐮�
-     */
-    public static MailAccount getMailAccount(String from, String user, String pass) {
-        ACCOUNT.setFrom(StringUtils.blankToDefault(from, ACCOUNT.getFrom()));
-        ACCOUNT.setUser(StringUtils.blankToDefault(user, ACCOUNT.getUser()));
-        ACCOUNT.setPass(StringUtils.blankToDefault(pass, ACCOUNT.getPass()));
-        return ACCOUNT;
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�佹枃鏈偖浠讹紝鍙戦�佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
-     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to      鏀朵欢浜�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String sendText(String to, String subject, String content, File... files) {
-        return send(to, subject, content, false, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
-     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to      鏀朵欢浜�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String sendHtml(String to, String subject, String content, File... files) {
-        return send(to, subject, content, true, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
-     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to      鏀朵欢浜�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param isHtml  鏄惁涓篐TML
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     */
-    public static String send(String to, String subject, String content, boolean isHtml, File... files) {
-        return send(splitAddress(to), subject, content, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
-     * 澶氫釜鏀朵欢浜恒�佹妱閫佷汉銆佸瘑閫佷汉鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to      鏀朵欢浜猴紝鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     * @param cc      鎶勯�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     * @param bcc     瀵嗛�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param isHtml  鏄惁涓篐TML
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.0.3
-     */
-    public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
-        return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�佹枃鏈偖浠讹紝鍙戦�佺粰澶氫汉
-     *
-     * @param tos     鏀朵欢浜哄垪琛�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     */
-    public static String sendText(Collection<String> tos, String subject, String content, File... files) {
-        return send(tos, subject, content, false, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰澶氫汉
-     *
-     * @param tos     鏀朵欢浜哄垪琛�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String sendHtml(Collection<String> tos, String subject, String content, File... files) {
-        return send(tos, subject, content, true, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
-     *
-     * @param tos     鏀朵欢浜哄垪琛�
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param isHtml  鏄惁涓篐TML
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     */
-    public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
-        return send(tos, null, null, subject, content, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
-     *
-     * @param tos     鏀朵欢浜哄垪琛�
-     * @param ccs     鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param bccs    瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param subject 鏍囬
-     * @param content 姝f枃
-     * @param isHtml  鏄惁涓篐TML
-     * @param files   闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.0.3
-     */
-    public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
-        return send(getMailAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
-    }
-
-    // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount 閭欢璁よ瘉瀵硅薄
-     * @param to          鏀朵欢浜猴紝澶氫釜鏀朵欢浜洪�楀彿鎴栬�呭垎鍙烽殧寮�
-     * @param subject     鏍囬
-     * @param content     姝f枃
-     * @param isHtml      鏄惁涓篐TML鏍煎紡
-     * @param files       闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
-        return send(mailAccount, splitAddress(to), subject, content, isHtml, files);
-    }
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount 閭欢甯愭埛淇℃伅
-     * @param tos         鏀朵欢浜哄垪琛�
-     * @param subject     鏍囬
-     * @param content     姝f枃
-     * @param isHtml      鏄惁涓篐TML鏍煎紡
-     * @param files       闄勪欢鍒楄〃
-     * @return message-id
-     */
-    public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
-        return send(mailAccount, tos, null, null, subject, content, isHtml, files);
-    }
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount 閭欢甯愭埛淇℃伅
-     * @param tos         鏀朵欢浜哄垪琛�
-     * @param ccs         鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param bccs        瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param subject     鏍囬
-     * @param content     姝f枃
-     * @param isHtml      鏄惁涓篐TML鏍煎紡
-     * @param files       闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.0.3
-     */
-    public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
-        return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰鍗曚釜鎴栧涓敹浠朵汉<br>
-     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to       鏀朵欢浜�
-     * @param subject  鏍囬
-     * @param content  姝f枃
-     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param files    闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
-        return send(to, subject, content, imageMap, true, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
-     * 澶氫釜鏀朵欢浜哄彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to       鏀朵欢浜�
-     * @param subject  鏍囬
-     * @param content  姝f枃
-     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml   鏄惁涓篐TML
-     * @param files    闄勪欢鍒楄〃
-     * @return message-id
-     */
-    public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        return send(splitAddress(to), subject, content, imageMap, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佸崟涓垨澶氫釜鏀朵欢浜�<br>
-     * 澶氫釜鏀朵欢浜恒�佹妱閫佷汉銆佸瘑閫佷汉鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     *
-     * @param to       鏀朵欢浜猴紝鍙互浣跨敤閫楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     * @param cc       鎶勯�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     * @param bcc      瀵嗛�佷汉锛屽彲浠ヤ娇鐢ㄩ�楀彿鈥�,鈥濆垎闅旓紝涔熷彲浠ラ�氳繃鍒嗗彿鈥�;鈥濆垎闅�
-     * @param subject  鏍囬
-     * @param content  姝f枃
-     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml   鏄惁涓篐TML
-     * @param files    闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.0.3
-     */
-    public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�丠TML閭欢锛屽彂閫佺粰澶氫汉
-     *
-     * @param tos      鏀朵欢浜哄垪琛�
-     * @param subject  鏍囬
-     * @param content  姝f枃
-     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param files    闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
-        return send(tos, subject, content, imageMap, true, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
-     *
-     * @param tos      鏀朵欢浜哄垪琛�
-     * @param subject  鏍囬
-     * @param content  姝f枃
-     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml   鏄惁涓篐TML
-     * @param files    闄勪欢鍒楄〃
-     * @return message-id
-     */
-    public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        return send(tos, null, null, subject, content, imageMap, isHtml, files);
-    }
-
-    /**
-     * 浣跨敤閰嶇疆鏂囦欢涓缃殑璐︽埛鍙戦�侀偖浠讹紝鍙戦�佺粰澶氫汉
-     *
-     * @param tos      鏀朵欢浜哄垪琛�
-     * @param ccs      鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param bccs     瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param subject  鏍囬
-     * @param content  姝f枃
-     * @param imageMap 鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml   鏄惁涓篐TML
-     * @param files    闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.0.3
-     */
-    public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        return send(getMailAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
-    }
-
-    // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount 閭欢璁よ瘉瀵硅薄
-     * @param to          鏀朵欢浜猴紝澶氫釜鏀朵欢浜洪�楀彿鎴栬�呭垎鍙烽殧寮�
-     * @param subject     鏍囬
-     * @param content     姝f枃
-     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml      鏄惁涓篐TML鏍煎紡
-     * @param files       闄勪欢鍒楄〃
-     * @return message-id
-     * @since 3.2.0
-     */
-    public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
-    }
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount 閭欢甯愭埛淇℃伅
-     * @param tos         鏀朵欢浜哄垪琛�
-     * @param subject     鏍囬
-     * @param content     姝f枃
-     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml      鏄惁涓篐TML鏍煎紡
-     * @param files       闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.6.3
-     */
-    public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
-    }
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount 閭欢甯愭埛淇℃伅
-     * @param tos         鏀朵欢浜哄垪琛�
-     * @param ccs         鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param bccs        瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param subject     鏍囬
-     * @param content     姝f枃
-     * @param imageMap    鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:$IMAGE_PLACEHOLDER
-     * @param isHtml      鏄惁涓篐TML鏍煎紡
-     * @param files       闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.6.3
-     */
-    public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
-                              boolean isHtml, File... files) {
-        return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
-    }
-
-    /**
-     * 鏍规嵁閰嶇疆鏂囦欢锛岃幏鍙栭偖浠跺鎴风浼氳瘽
-     *
-     * @param mailAccount 閭欢璐︽埛閰嶇疆
-     * @param isSingleton 鏄惁鍗曚緥锛堝叏灞�鍏变韩浼氳瘽锛�
-     * @return {@link Session}
-     * @since 5.5.7
-     */
-    public static Session getSession(MailAccount mailAccount, boolean isSingleton) {
-        Authenticator authenticator = null;
-        if (mailAccount.isAuth()) {
-            authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
-        }
-
-        return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) //
-            : Session.getInstance(mailAccount.getSmtpProps(), authenticator);
-    }
-
-    // ------------------------------------------------------------------------------------------------------------------------ Private method start
-
-    /**
-     * 鍙戦�侀偖浠剁粰澶氫汉
-     *
-     * @param mailAccount      閭欢甯愭埛淇℃伅
-     * @param useGlobalSession 鏄惁鍏ㄥ眬鍏变韩Session
-     * @param tos              鏀朵欢浜哄垪琛�
-     * @param ccs              鎶勯�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param bccs             瀵嗛�佷汉鍒楄〃锛屽彲浠ヤ负null鎴栫┖
-     * @param subject          鏍囬
-     * @param content          姝f枃
-     * @param imageMap         鍥剧墖涓庡崰浣嶇锛屽崰浣嶇鏍煎紡涓篶id:${cid}
-     * @param isHtml           鏄惁涓篐TML鏍煎紡
-     * @param files            闄勪欢鍒楄〃
-     * @return message-id
-     * @since 4.6.3
-     */
-    private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
-                               Map<String, InputStream> imageMap, boolean isHtml, File... files) {
-        final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession);
-
-        // 鍙�夋妱閫佷汉
-        if (CollUtil.isNotEmpty(ccs)) {
-            mail.setCcs(ccs.toArray(new String[0]));
-        }
-        // 鍙�夊瘑閫佷汉
-        if (CollUtil.isNotEmpty(bccs)) {
-            mail.setBccs(bccs.toArray(new String[0]));
-        }
-
-        mail.setTos(tos.toArray(new String[0]));
-        mail.setTitle(subject);
-        mail.setContent(content);
-        mail.setHtml(isHtml);
-        mail.setFiles(files);
-
-        // 鍥剧墖
-        if (MapUtil.isNotEmpty(imageMap)) {
-            for (Map.Entry<String, InputStream> entry : imageMap.entrySet()) {
-                mail.addImage(entry.getKey(), entry.getValue());
-                // 鍏抽棴娴�
-                IoUtil.close(entry.getValue());
-            }
-        }
-
-        return mail.send();
-    }
-
-    /**
-     * 灏嗗涓仈绯讳汉杞负鍒楄〃锛屽垎闅旂涓洪�楀彿鎴栬�呭垎鍙�
-     *
-     * @param addresses 澶氫釜鑱旂郴浜猴紝濡傛灉涓虹┖杩斿洖null
-     * @return 鑱旂郴浜哄垪琛�
-     */
-    private static List<String> splitAddress(String addresses) {
-        if (StrUtil.isBlank(addresses)) {
-            return null;
-        }
-
-        List<String> result;
-        if (StrUtil.contains(addresses, CharUtil.COMMA)) {
-            result = StrUtil.splitTrim(addresses, CharUtil.COMMA);
-        } else if (StrUtil.contains(addresses, ';')) {
-            result = StrUtil.splitTrim(addresses, ';');
-        } else {
-            result = CollUtil.newArrayList(addresses);
-        }
-        return result;
-    }
-    // ------------------------------------------------------------------------------------------------------------------------ Private method end
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/UserPassAuthenticator.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/UserPassAuthenticator.java
deleted file mode 100644
index d3e0fc8..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/email/UserPassAuthenticator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.ruoyi.common.utils.email;
-
-import jakarta.mail.Authenticator;
-import jakarta.mail.PasswordAuthentication;
-
-/**
- * 鐢ㄦ埛鍚嶅瘑鐮侀獙璇佸櫒
- *
- * @author looly
- * @since 3.1.2
- */
-public class UserPassAuthenticator extends Authenticator {
-
-	private final String user;
-	private final String pass;
-
-	/**
-	 * 鏋勯��
-	 *
-	 * @param user 鐢ㄦ埛鍚�
-	 * @param pass 瀵嗙爜
-	 */
-	public UserPassAuthenticator(String user, String pass) {
-		this.user = user;
-		this.pass = pass;
-	}
-
-	@Override
-	protected PasswordAuthentication getPasswordAuthentication() {
-		return new PasswordAuthentication(this.user, this.pass);
-	}
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
deleted file mode 100644
index 8bd6a0f..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.ruoyi.common.utils.file;
-
-import cn.hutool.core.io.FileUtil;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-
-/**
- * 鏂囦欢澶勭悊宸ュ叿绫�
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class FileUtils extends FileUtil {
-
-    /**
-     * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
-     *
-     * @param response     鍝嶅簲瀵硅薄
-     * @param realFileName 鐪熷疄鏂囦欢鍚�
-     */
-    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
-        String percentEncodedFileName = percentEncode(realFileName);
-
-        StringBuilder contentDispositionValue = new StringBuilder();
-        contentDispositionValue.append("attachment; filename=")
-            .append(percentEncodedFileName)
-            .append(";")
-            .append("filename*=")
-            .append("utf-8''")
-            .append(percentEncodedFileName);
-
-        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
-        response.setHeader("Content-disposition", contentDispositionValue.toString());
-        response.setHeader("download-filename", percentEncodedFileName);
-    }
-
-    /**
-     * 鐧惧垎鍙风紪鐮佸伐鍏锋柟娉�
-     *
-     * @param s 闇�瑕佺櫨鍒嗗彿缂栫爜鐨勫瓧绗︿覆
-     * @return 鐧惧垎鍙风紪鐮佸悗鐨勫瓧绗︿覆
-     */
-    public static String percentEncode(String s) throws UnsupportedEncodingException {
-        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
-        return encode.replaceAll("\\+", "%20");
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
deleted file mode 100644
index 6ca97fe..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.ruoyi.common.utils.file;
-
-/**
- * 濯掍綋绫诲瀷宸ュ叿绫�
- *
- * @author ruoyi
- */
-public class MimeTypeUtils {
-    public static final String IMAGE_PNG = "image/png";
-
-    public static final String IMAGE_JPG = "image/jpg";
-
-    public static final String IMAGE_JPEG = "image/jpeg";
-
-    public static final String IMAGE_BMP = "image/bmp";
-
-    public static final String IMAGE_GIF = "image/gif";
-
-    public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
-
-    public static final String[] FLASH_EXTENSION = {"swf", "flv"};
-
-    public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
-        "asf", "rm", "rmvb"};
-
-    public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"};
-
-    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
-        // 鍥剧墖
-        "bmp", "gif", "jpg", "jpeg", "png",
-        // word excel powerpoint
-        "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
-        // 鍘嬬缉鏂囦欢
-        "rar", "zip", "gz", "bz2",
-        // 瑙嗛鏍煎紡
-        "mp4", "avi", "rmvb",
-        // pdf
-        "pdf"};
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
deleted file mode 100644
index 8d3515e..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.ruoyi.common.utils.ip;
-
-import cn.hutool.core.lang.Dict;
-import cn.hutool.core.net.NetUtil;
-import cn.hutool.http.HtmlUtil;
-import cn.hutool.http.HttpUtil;
-import com.ruoyi.common.config.RuoYiConfig;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-/**
- * 鑾峰彇鍦板潃绫�
- *
- * @author Lion Li
- */
-@Slf4j
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class AddressUtils {
-
-    // IP鍦板潃鏌ヨ
-    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
-
-    // 鏈煡鍦板潃
-    public static final String UNKNOWN = "XX XX";
-
-    public static String getRealAddressByIP(String ip) {
-        String address = UNKNOWN;
-        if (StringUtils.isBlank(ip)) {
-            return address;
-        }
-        // 鍐呯綉涓嶆煡璇�
-        ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip);
-        if (NetUtil.isInnerIP(ip)) {
-            return "鍐呯綉IP";
-        }
-        if (RuoYiConfig.isAddressEnabled()) {
-            try {
-                String rspStr = HttpUtil.createGet(IP_URL)
-                    .body("ip=" + ip + "&json=true", Constants.GBK)
-                    .execute()
-                    .body();
-                if (StringUtils.isEmpty(rspStr)) {
-                    log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
-                    return UNKNOWN;
-                }
-                Dict obj = JsonUtils.parseMap(rspStr);
-                String region = obj.getStr("pro");
-                String city = obj.getStr("city");
-                return String.format("%s %s", region, city);
-            } catch (Exception e) {
-                log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
-            }
-        }
-        return UNKNOWN;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
deleted file mode 100644
index bbe3471..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
+++ /dev/null
@@ -1,328 +0,0 @@
-package com.ruoyi.common.utils.poi;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.io.resource.ClassPathResource;
-import cn.hutool.core.util.IdUtil;
-import com.alibaba.excel.EasyExcel;
-import com.alibaba.excel.ExcelWriter;
-import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
-import com.alibaba.excel.write.metadata.WriteSheet;
-import com.alibaba.excel.write.metadata.fill.FillConfig;
-import com.alibaba.excel.write.metadata.fill.FillWrapper;
-import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
-import com.ruoyi.common.convert.ExcelBigNumberConvert;
-import com.ruoyi.common.excel.CellMergeStrategy;
-import com.ruoyi.common.excel.DefaultExcelListener;
-import com.ruoyi.common.excel.ExcelListener;
-import com.ruoyi.common.excel.ExcelResult;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.FileUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import jakarta.servlet.ServletOutputStream;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Excel鐩稿叧澶勭悊
- *
- * @author Lion Li
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ExcelUtil {
-
-    /**
-     * 鍚屾瀵煎叆(閫傜敤浜庡皬鏁版嵁閲�)
-     *
-     * @param is 杈撳叆娴�
-     * @return 杞崲鍚庨泦鍚�
-     */
-    public static <T> List<T> importExcel(InputStream is, Class<T> clazz) {
-        return EasyExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync();
-    }
-
-
-    /**
-     * 浣跨敤鏍¢獙鐩戝惉鍣� 寮傛瀵煎叆 鍚屾杩斿洖
-     *
-     * @param is         杈撳叆娴�
-     * @param clazz      瀵硅薄绫诲瀷
-     * @param isValidate 鏄惁 Validator 妫�楠� 榛樿涓烘槸
-     * @return 杞崲鍚庨泦鍚�
-     */
-    public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, boolean isValidate) {
-        DefaultExcelListener<T> listener = new DefaultExcelListener<>(isValidate);
-        EasyExcel.read(is, clazz, listener).sheet().doRead();
-        return listener.getExcelResult();
-    }
-
-    /**
-     * 浣跨敤鑷畾涔夌洃鍚櫒 寮傛瀵煎叆 鑷畾涔夎繑鍥�
-     *
-     * @param is       杈撳叆娴�
-     * @param clazz    瀵硅薄绫诲瀷
-     * @param listener 鑷畾涔夌洃鍚櫒
-     * @return 杞崲鍚庨泦鍚�
-     */
-    public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) {
-        EasyExcel.read(is, clazz, listener).sheet().doRead();
-        return listener.getExcelResult();
-    }
-
-    /**
-     * 瀵煎嚭excel
-     *
-     * @param list      瀵煎嚭鏁版嵁闆嗗悎
-     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
-     * @param clazz     瀹炰綋绫�
-     * @param response  鍝嶅簲浣�
-     */
-    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) {
-        try {
-            resetResponse(sheetName, response);
-            ServletOutputStream os = response.getOutputStream();
-            exportExcel(list, sheetName, clazz, false, os);
-        } catch (IOException e) {
-            throw new RuntimeException("瀵煎嚭Excel寮傚父");
-        }
-    }
-
-    /**
-     * 瀵煎嚭excel
-     *
-     * @param list      瀵煎嚭鏁版嵁闆嗗悎
-     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
-     * @param clazz     瀹炰綋绫�
-     * @param merge     鏄惁鍚堝苟鍗曞厓鏍�
-     * @param response  鍝嶅簲浣�
-     */
-    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response) {
-        try {
-            resetResponse(sheetName, response);
-            ServletOutputStream os = response.getOutputStream();
-            exportExcel(list, sheetName, clazz, merge, os);
-        } catch (IOException e) {
-            throw new RuntimeException("瀵煎嚭Excel寮傚父");
-        }
-    }
-
-    /**
-     * 瀵煎嚭excel
-     *
-     * @param list      瀵煎嚭鏁版嵁闆嗗悎
-     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
-     * @param clazz     瀹炰綋绫�
-     * @param os        杈撳嚭娴�
-     */
-    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) {
-        exportExcel(list, sheetName, clazz, false, os);
-    }
-
-    /**
-     * 瀵煎嚭excel
-     *
-     * @param list      瀵煎嚭鏁版嵁闆嗗悎
-     * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
-     * @param clazz     瀹炰綋绫�
-     * @param merge     鏄惁鍚堝苟鍗曞厓鏍�
-     * @param os        杈撳嚭娴�
-     */
-    public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os) {
-        ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
-            .autoCloseStream(false)
-            // 鑷姩閫傞厤
-            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
-            // 澶ф暟鍊艰嚜鍔ㄨ浆鎹� 闃叉澶辩湡
-            .registerConverter(new ExcelBigNumberConvert())
-            .sheet(sheetName);
-        if (merge) {
-            // 鍚堝苟澶勭悊鍣�
-            builder.registerWriteHandler(new CellMergeStrategy(list, true));
-        }
-        builder.doWrite(list);
-    }
-
-    /**
-     * 鍗曡〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {.灞炴�
-     *
-     * @param filename     鏂囦欢鍚�
-     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
-     *                     渚嬪: excel/temp.xlsx
-     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
-     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
-     * @param response     鍝嶅簲浣�
-     */
-    public static void exportTemplate(List<Object> data, String filename, String templatePath, HttpServletResponse response) {
-        try {
-            resetResponse(filename, response);
-            ServletOutputStream os = response.getOutputStream();
-            exportTemplate(data, templatePath, os);
-        } catch (IOException e) {
-            throw new RuntimeException("瀵煎嚭Excel寮傚父");
-        }
-    }
-
-    /**
-     * 鍗曡〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {.灞炴�
-     *
-     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
-     *                     渚嬪: excel/temp.xlsx
-     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
-     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
-     * @param os           杈撳嚭娴�
-     */
-    public static void exportTemplate(List<Object> data, String templatePath, OutputStream os) {
-        ClassPathResource templateResource = new ClassPathResource(templatePath);
-        ExcelWriter excelWriter = EasyExcel.write(os)
-            .withTemplate(templateResource.getStream())
-            .autoCloseStream(false)
-            // 澶ф暟鍊艰嚜鍔ㄨ浆鎹� 闃叉澶辩湡
-            .registerConverter(new ExcelBigNumberConvert())
-            .build();
-        WriteSheet writeSheet = EasyExcel.writerSheet().build();
-        if (CollUtil.isEmpty(data)) {
-            throw new IllegalArgumentException("鏁版嵁涓虹┖");
-        }
-        // 鍗曡〃澶氭暟鎹鍑� 妯℃澘鏍煎紡涓� {.灞炴�
-        for (Object d : data) {
-            excelWriter.fill(d, writeSheet);
-        }
-        excelWriter.finish();
-    }
-
-    /**
-     * 澶氳〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {key.灞炴�
-     *
-     * @param filename     鏂囦欢鍚�
-     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
-     *                     渚嬪: excel/temp.xlsx
-     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
-     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
-     * @param response     鍝嶅簲浣�
-     */
-    public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) {
-        try {
-            resetResponse(filename, response);
-            ServletOutputStream os = response.getOutputStream();
-            exportTemplateMultiList(data, templatePath, os);
-        } catch (IOException e) {
-            throw new RuntimeException("瀵煎嚭Excel寮傚父");
-        }
-    }
-
-    /**
-     * 澶氳〃澶氭暟鎹ā鏉垮鍑� 妯℃澘鏍煎紡涓� {key.灞炴�
-     *
-     * @param templatePath 妯℃澘璺緞 resource 鐩綍涓嬬殑璺緞鍖呮嫭妯℃澘鏂囦欢鍚�
-     *                     渚嬪: excel/temp.xlsx
-     *                     閲嶇偣: 妯℃澘鏂囦欢蹇呴』鏀剧疆鍒板惎鍔ㄧ被瀵瑰簲鐨� resource 鐩綍涓�
-     * @param data         妯℃澘闇�瑕佺殑鏁版嵁
-     * @param os           杈撳嚭娴�
-     */
-    public static void exportTemplateMultiList(Map<String, Object> data, String templatePath, OutputStream os) {
-        ClassPathResource templateResource = new ClassPathResource(templatePath);
-        ExcelWriter excelWriter = EasyExcel.write(os)
-            .withTemplate(templateResource.getStream())
-            .autoCloseStream(false)
-            // 澶ф暟鍊艰嚜鍔ㄨ浆鎹� 闃叉澶辩湡
-            .registerConverter(new ExcelBigNumberConvert())
-            .build();
-        WriteSheet writeSheet = EasyExcel.writerSheet().build();
-        if (CollUtil.isEmpty(data)) {
-            throw new IllegalArgumentException("鏁版嵁涓虹┖");
-        }
-        for (Map.Entry<String, Object> map : data.entrySet()) {
-            // 璁剧疆鍒楄〃鍚庣画杩樻湁鏁版嵁
-            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
-            if (map.getValue() instanceof Collection) {
-                // 澶氳〃瀵煎嚭蹇呴』浣跨敤 FillWrapper
-                excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet);
-            } else {
-                excelWriter.fill(map.getValue(), writeSheet);
-            }
-        }
-        excelWriter.finish();
-    }
-
-    /**
-     * 閲嶇疆鍝嶅簲浣�
-     */
-    private static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException {
-        String filename = encodingFilename(sheetName);
-        FileUtils.setAttachmentResponseHeader(response, filename);
-        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
-    }
-
-    /**
-     * 瑙f瀽瀵煎嚭鍊� 0=鐢�,1=濂�,2=鏈煡
-     *
-     * @param propertyValue 鍙傛暟鍊�
-     * @param converterExp  缈昏瘧娉ㄨВ
-     * @param separator     鍒嗛殧绗�
-     * @return 瑙f瀽鍚庡��
-     */
-    public static String convertByExp(String propertyValue, String converterExp, String separator) {
-        StringBuilder propertyString = new StringBuilder();
-        String[] convertSource = converterExp.split(",");
-        for (String item : convertSource) {
-            String[] itemArray = item.split("=");
-            if (StringUtils.containsAny(propertyValue, separator)) {
-                for (String value : propertyValue.split(separator)) {
-                    if (itemArray[0].equals(value)) {
-                        propertyString.append(itemArray[1] + separator);
-                        break;
-                    }
-                }
-            } else {
-                if (itemArray[0].equals(propertyValue)) {
-                    return itemArray[1];
-                }
-            }
-        }
-        return StringUtils.stripEnd(propertyString.toString(), separator);
-    }
-
-    /**
-     * 鍙嶅悜瑙f瀽鍊� 鐢�=0,濂�=1,鏈煡=2
-     *
-     * @param propertyValue 鍙傛暟鍊�
-     * @param converterExp  缈昏瘧娉ㄨВ
-     * @param separator     鍒嗛殧绗�
-     * @return 瑙f瀽鍚庡��
-     */
-    public static String reverseByExp(String propertyValue, String converterExp, String separator) {
-        StringBuilder propertyString = new StringBuilder();
-        String[] convertSource = converterExp.split(",");
-        for (String item : convertSource) {
-            String[] itemArray = item.split("=");
-            if (StringUtils.containsAny(propertyValue, separator)) {
-                for (String value : propertyValue.split(separator)) {
-                    if (itemArray[1].equals(value)) {
-                        propertyString.append(itemArray[0] + separator);
-                        break;
-                    }
-                }
-            } else {
-                if (itemArray[1].equals(propertyValue)) {
-                    return itemArray[0];
-                }
-            }
-        }
-        return StringUtils.stripEnd(propertyString.toString(), separator);
-    }
-
-    /**
-     * 缂栫爜鏂囦欢鍚�
-     */
-    public static String encodingFilename(String filename) {
-        return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx";
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/CacheUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/CacheUtils.java
deleted file mode 100644
index 9e0b09b..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/CacheUtils.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.ruoyi.common.utils.redis;
-
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.redisson.api.RMap;
-import org.springframework.cache.Cache;
-import org.springframework.cache.CacheManager;
-
-import java.util.Set;
-
-/**
- * 缂撳瓨鎿嶄綔宸ュ叿绫� {@link }
- *
- * @author Michelle.Chung
- * @date 2022/8/13
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-@SuppressWarnings(value = {"unchecked"})
-public class CacheUtils {
-
-    private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);
-
-    /**
-     * 鑾峰彇缂撳瓨缁勫唴鎵�鏈夌殑KEY
-     *
-     * @param cacheNames 缂撳瓨缁勫悕绉�
-     */
-    public static Set<Object> keys(String cacheNames) {
-        RMap<Object, Object> rmap = (RMap<Object, Object>) CACHE_MANAGER.getCache(cacheNames).getNativeCache();
-        return rmap.keySet();
-    }
-
-    /**
-     * 鑾峰彇缂撳瓨鍊�
-     *
-     * @param cacheNames 缂撳瓨缁勫悕绉�
-     * @param key        缂撳瓨key
-     */
-    public static <T> T get(String cacheNames, Object key) {
-        Cache.ValueWrapper wrapper = CACHE_MANAGER.getCache(cacheNames).get(key);
-        return wrapper != null ? (T) wrapper.get() : null;
-    }
-
-    /**
-     * 淇濆瓨缂撳瓨鍊�
-     *
-     * @param cacheNames 缂撳瓨缁勫悕绉�
-     * @param key        缂撳瓨key
-     * @param value      缂撳瓨鍊�
-     */
-    public static void put(String cacheNames, Object key, Object value) {
-        CACHE_MANAGER.getCache(cacheNames).put(key, value);
-    }
-
-    /**
-     * 鍒犻櫎缂撳瓨鍊�
-     *
-     * @param cacheNames 缂撳瓨缁勫悕绉�
-     * @param key        缂撳瓨key
-     */
-    public static void evict(String cacheNames, Object key) {
-        CACHE_MANAGER.getCache(cacheNames).evict(key);
-    }
-
-    /**
-     * 娓呯┖缂撳瓨鍊�
-     *
-     * @param cacheNames 缂撳瓨缁勫悕绉�
-     */
-    public static void clear(String cacheNames) {
-        CACHE_MANAGER.getCache(cacheNames).clear();
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java
deleted file mode 100644
index 7a4bce4..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package com.ruoyi.common.utils.redis;
-
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.redisson.api.*;
-
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-
-/**
- * 鍒嗗竷寮忛槦鍒楀伐鍏�
- * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
- * 瑕佹眰 redis 5.X 浠ヤ笂
- *
- * @author Lion Li
- * @version 3.6.0 鏂板
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class QueueUtils {
-
-    private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
-
-
-    /**
-     * 鑾峰彇瀹㈡埛绔疄渚�
-     */
-    public static RedissonClient getClient() {
-        return CLIENT;
-    }
-
-    /**
-     * 娣诲姞鏅�氶槦鍒楁暟鎹�
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param data      鏁版嵁
-     */
-    public static <T> boolean addQueueObject(String queueName, T data) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        return queue.offer(data);
-    }
-
-    /**
-     * 閫氱敤鑾峰彇涓�涓槦鍒楁暟鎹� 娌℃湁鏁版嵁杩斿洖 null(涓嶆敮鎸佸欢杩熼槦鍒�)
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    public static <T> T getQueueObject(String queueName) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        return queue.poll();
-    }
-
-    /**
-     * 閫氱敤鍒犻櫎闃熷垪鏁版嵁(涓嶆敮鎸佸欢杩熼槦鍒�)
-     */
-    public static <T> boolean removeQueueObject(String queueName, T data) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        return queue.remove(data);
-    }
-
-    /**
-     * 閫氱敤閿�姣侀槦鍒� 鎵�鏈夐樆濉炵洃鍚� 鎶ラ敊(涓嶆敮鎸佸欢杩熼槦鍒�)
-     */
-    public static <T> boolean destroyQueue(String queueName) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        return queue.delete();
-    }
-
-    /**
-     * 娣诲姞寤惰繜闃熷垪鏁版嵁 榛樿姣
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param data      鏁版嵁
-     * @param time      寤惰繜鏃堕棿
-     */
-    public static <T> void addDelayedQueueObject(String queueName, T data, long time) {
-        addDelayedQueueObject(queueName, data, time, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * 娣诲姞寤惰繜闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param data      鏁版嵁
-     * @param time      寤惰繜鏃堕棿
-     * @param timeUnit  鍗曚綅
-     */
-    public static <T> void addDelayedQueueObject(String queueName, T data, long time, TimeUnit timeUnit) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
-        delayedQueue.offer(data, time, timeUnit);
-    }
-
-    /**
-     * 鑾峰彇涓�涓欢杩熼槦鍒楁暟鎹� 娌℃湁鏁版嵁杩斿洖 null
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    public static <T> T getDelayedQueueObject(String queueName) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
-        return delayedQueue.poll();
-    }
-
-    /**
-     * 鍒犻櫎寤惰繜闃熷垪鏁版嵁
-     */
-    public static <T> boolean removeDelayedQueueObject(String queueName, T data) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
-        return delayedQueue.remove(data);
-    }
-
-    /**
-     * 閿�姣佸欢杩熼槦鍒� 鎵�鏈夐樆濉炵洃鍚� 鎶ラ敊
-     */
-    public static <T> void destroyDelayedQueue(String queueName) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        RDelayedQueue<T> delayedQueue = CLIENT.getDelayedQueue(queue);
-        delayedQueue.destroy();
-    }
-
-    /**
-     * 娣诲姞浼樺厛闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param data      鏁版嵁
-     */
-    public static <T> boolean addPriorityQueueObject(String queueName, T data) {
-        RPriorityBlockingQueue<T> priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName);
-        return priorityBlockingQueue.offer(data);
-    }
-
-    /**
-     * 灏濊瘯璁剧疆 鏈夌晫闃熷垪 瀹归噺 鐢ㄤ簬闄愬埗鏁伴噺
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param capacity  瀹归噺
-     */
-    public static <T> boolean trySetBoundedQueueCapacity(String queueName, int capacity) {
-        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
-        return boundedBlockingQueue.trySetCapacity(capacity);
-    }
-
-    /**
-     * 灏濊瘯璁剧疆 鏈夌晫闃熷垪 瀹归噺 鐢ㄤ簬闄愬埗鏁伴噺
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param capacity  瀹归噺
-     * @param destroy   宸插瓨鍦ㄦ槸鍚﹂攢姣�
-     */
-    public static <T> boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) {
-        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
-        if (boundedBlockingQueue.isExists() && destroy) {
-            destroyQueue(queueName);
-        }
-        return boundedBlockingQueue.trySetCapacity(capacity);
-    }
-
-    /**
-     * 娣诲姞鏈夌晫闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param data      鏁版嵁
-     * @return 娣诲姞鎴愬姛 true 宸茶揪鍒扮晫闄� false
-     */
-    public static <T> boolean addBoundedQueueObject(String queueName, T data) {
-        RBoundedBlockingQueue<T> boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName);
-        return boundedBlockingQueue.offer(data);
-    }
-
-    /**
-     * 璁㈤槄闃诲闃熷垪(鍙闃呮墍鏈夊疄鐜扮被 渚嬪: 寤惰繜 浼樺厛 鏈夌晫 绛�)
-     */
-    public static <T> void subscribeBlockingQueue(String queueName, Consumer<T> consumer) {
-        RBlockingQueue<T> queue = CLIENT.getBlockingQueue(queueName);
-        queue.subscribeOnElements(consumer);
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java
deleted file mode 100644
index 1623808..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java
+++ /dev/null
@@ -1,462 +0,0 @@
-package com.ruoyi.common.utils.redis;
-
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.redisson.api.*;
-
-import java.time.Duration;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * redis 宸ュ叿绫�
- *
- * @author Lion Li
- * @version 3.1.0 鏂板
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-@SuppressWarnings(value = {"unchecked", "rawtypes"})
-public class RedisUtils {
-
-    private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
-
-    /**
-     * 闄愭祦
-     *
-     * @param key          闄愭祦key
-     * @param rateType     闄愭祦绫诲瀷
-     * @param rate         閫熺巼
-     * @param rateInterval 閫熺巼闂撮殧
-     * @return -1 琛ㄧず澶辫触
-     */
-    public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
-        RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
-        rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
-        if (rateLimiter.tryAcquire()) {
-            return rateLimiter.availablePermits();
-        } else {
-            return -1L;
-        }
-    }
-
-    /**
-     * 鑾峰彇瀹㈡埛绔疄渚�
-     */
-    public static RedissonClient getClient() {
-        return CLIENT;
-    }
-
-    /**
-     * 鍙戝竷閫氶亾娑堟伅
-     *
-     * @param channelKey 閫氶亾key
-     * @param msg        鍙戦�佹暟鎹�
-     * @param consumer   鑷畾涔夊鐞�
-     */
-    public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
-        RTopic topic = CLIENT.getTopic(channelKey);
-        topic.publish(msg);
-        consumer.accept(msg);
-    }
-
-    public static <T> void publish(String channelKey, T msg) {
-        RTopic topic = CLIENT.getTopic(channelKey);
-        topic.publish(msg);
-    }
-
-    /**
-     * 璁㈤槄閫氶亾鎺ユ敹娑堟伅
-     *
-     * @param channelKey 閫氶亾key
-     * @param clazz      娑堟伅绫诲瀷
-     * @param consumer   鑷畾涔夊鐞�
-     */
-    public static <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
-        RTopic topic = CLIENT.getTopic(channelKey);
-        topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
-    }
-
-    /**
-     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
-     *
-     * @param key   缂撳瓨鐨勯敭鍊�
-     * @param value 缂撳瓨鐨勫��
-     */
-    public static <T> void setCacheObject(final String key, final T value) {
-        setCacheObject(key, value, false);
-    }
-
-    /**
-     * 缂撳瓨鍩烘湰鐨勫璞★紝淇濈暀褰撳墠瀵硅薄 TTL 鏈夋晥鏈�
-     *
-     * @param key       缂撳瓨鐨勯敭鍊�
-     * @param value     缂撳瓨鐨勫��
-     * @param isSaveTtl 鏄惁淇濈暀TTL鏈夋晥鏈�(渚嬪: set涔嬪墠ttl鍓╀綑90 set涔嬪悗杩樻槸涓�90)
-     * @since Redis 6.X 浠ヤ笂浣跨敤 setAndKeepTTL 鍏煎 5.X 鏂规
-     */
-    public static <T> void setCacheObject(final String key, final T value, final boolean isSaveTtl) {
-        RBucket<T> bucket = CLIENT.getBucket(key);
-        if (isSaveTtl) {
-            try {
-                bucket.setAndKeepTTL(value);
-            } catch (Exception e) {
-                long timeToLive = bucket.remainTimeToLive();
-                setCacheObject(key, value, Duration.ofMillis(timeToLive));
-            }
-        } else {
-            bucket.set(value);
-        }
-    }
-
-    /**
-     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
-     *
-     * @param key      缂撳瓨鐨勯敭鍊�
-     * @param value    缂撳瓨鐨勫��
-     * @param duration 鏃堕棿
-     */
-    public static <T> void setCacheObject(final String key, final T value, final Duration duration) {
-        RBatch batch = CLIENT.createBatch();
-        RBucketAsync<T> bucket = batch.getBucket(key);
-        bucket.setAsync(value);
-        bucket.expireAsync(duration);
-        batch.execute();
-    }
-
-    /**
-     * 娉ㄥ唽瀵硅薄鐩戝惉鍣�
-     * <p>
-     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
-     *
-     * @param key      缂撳瓨鐨勯敭鍊�
-     * @param listener 鐩戝惉鍣ㄩ厤缃�
-     */
-    public static <T> void addObjectListener(final String key, final ObjectListener listener) {
-        RBucket<T> result = CLIENT.getBucket(key);
-        result.addListener(listener);
-    }
-
-    /**
-     * 璁剧疆鏈夋晥鏃堕棿
-     *
-     * @param key     Redis閿�
-     * @param timeout 瓒呮椂鏃堕棿
-     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
-     */
-    public static boolean expire(final String key, final long timeout) {
-        return expire(key, Duration.ofSeconds(timeout));
-    }
-
-    /**
-     * 璁剧疆鏈夋晥鏃堕棿
-     *
-     * @param key      Redis閿�
-     * @param duration 瓒呮椂鏃堕棿
-     * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
-     */
-    public static boolean expire(final String key, final Duration duration) {
-        RBucket rBucket = CLIENT.getBucket(key);
-        return rBucket.expire(duration);
-    }
-
-    /**
-     * 鑾峰緱缂撳瓨鐨勫熀鏈璞°��
-     *
-     * @param key 缂撳瓨閿��
-     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
-     */
-    public static <T> T getCacheObject(final String key) {
-        RBucket<T> rBucket = CLIENT.getBucket(key);
-        return rBucket.get();
-    }
-
-    /**
-     * 鑾峰緱key鍓╀綑瀛樻椿鏃堕棿
-     *
-     * @param key 缂撳瓨閿��
-     * @return 鍓╀綑瀛樻椿鏃堕棿
-     */
-    public static <T> long getTimeToLive(final String key) {
-        RBucket<T> rBucket = CLIENT.getBucket(key);
-        return rBucket.remainTimeToLive();
-    }
-
-    /**
-     * 鍒犻櫎鍗曚釜瀵硅薄
-     *
-     * @param key 缂撳瓨鐨勯敭鍊�
-     */
-    public static boolean deleteObject(final String key) {
-        return CLIENT.getBucket(key).delete();
-    }
-
-    /**
-     * 鍒犻櫎闆嗗悎瀵硅薄
-     *
-     * @param collection 澶氫釜瀵硅薄
-     */
-    public static void deleteObject(final Collection collection) {
-        RBatch batch = CLIENT.createBatch();
-        collection.forEach(t -> {
-            batch.getBucket(t.toString()).deleteAsync();
-        });
-        batch.execute();
-    }
-
-    /**
-     * 妫�鏌ョ紦瀛樺璞℃槸鍚﹀瓨鍦�
-     *
-     * @param key 缂撳瓨鐨勯敭鍊�
-     */
-    public static boolean isExistsObject(final String key) {
-        return CLIENT.getBucket(key).isExists();
-    }
-
-    /**
-     * 缂撳瓨List鏁版嵁
-     *
-     * @param key      缂撳瓨鐨勯敭鍊�
-     * @param dataList 寰呯紦瀛樼殑List鏁版嵁
-     * @return 缂撳瓨鐨勫璞�
-     */
-    public static <T> boolean setCacheList(final String key, final List<T> dataList) {
-        RList<T> rList = CLIENT.getList(key);
-        return rList.addAll(dataList);
-    }
-
-    /**
-     * 娉ㄥ唽List鐩戝惉鍣�
-     * <p>
-     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
-     *
-     * @param key      缂撳瓨鐨勯敭鍊�
-     * @param listener 鐩戝惉鍣ㄩ厤缃�
-     */
-    public static <T> void addListListener(final String key, final ObjectListener listener) {
-        RList<T> rList = CLIENT.getList(key);
-        rList.addListener(listener);
-    }
-
-    /**
-     * 鑾峰緱缂撳瓨鐨刲ist瀵硅薄
-     *
-     * @param key 缂撳瓨鐨勯敭鍊�
-     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
-     */
-    public static <T> List<T> getCacheList(final String key) {
-        RList<T> rList = CLIENT.getList(key);
-        return rList.readAll();
-    }
-
-    /**
-     * 缂撳瓨Set
-     *
-     * @param key     缂撳瓨閿��
-     * @param dataSet 缂撳瓨鐨勬暟鎹�
-     * @return 缂撳瓨鏁版嵁鐨勫璞�
-     */
-    public static <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
-        RSet<T> rSet = CLIENT.getSet(key);
-        return rSet.addAll(dataSet);
-    }
-
-    /**
-     * 娉ㄥ唽Set鐩戝惉鍣�
-     * <p>
-     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
-     *
-     * @param key      缂撳瓨鐨勯敭鍊�
-     * @param listener 鐩戝惉鍣ㄩ厤缃�
-     */
-    public static <T> void addSetListener(final String key, final ObjectListener listener) {
-        RSet<T> rSet = CLIENT.getSet(key);
-        rSet.addListener(listener);
-    }
-
-    /**
-     * 鑾峰緱缂撳瓨鐨剆et
-     *
-     * @param key 缂撳瓨鐨刱ey
-     * @return set瀵硅薄
-     */
-    public static <T> Set<T> getCacheSet(final String key) {
-        RSet<T> rSet = CLIENT.getSet(key);
-        return rSet.readAll();
-    }
-
-    /**
-     * 缂撳瓨Map
-     *
-     * @param key     缂撳瓨鐨勯敭鍊�
-     * @param dataMap 缂撳瓨鐨勬暟鎹�
-     */
-    public static <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
-        if (dataMap != null) {
-            RMap<String, T> rMap = CLIENT.getMap(key);
-            rMap.putAll(dataMap);
-        }
-    }
-
-    /**
-     * 娉ㄥ唽Map鐩戝惉鍣�
-     * <p>
-     * key 鐩戝惉鍣ㄩ渶寮�鍚� `notify-keyspace-events` 绛� redis 鐩稿叧閰嶇疆
-     *
-     * @param key      缂撳瓨鐨勯敭鍊�
-     * @param listener 鐩戝惉鍣ㄩ厤缃�
-     */
-    public static <T> void addMapListener(final String key, final ObjectListener listener) {
-        RMap<String, T> rMap = CLIENT.getMap(key);
-        rMap.addListener(listener);
-    }
-
-    /**
-     * 鑾峰緱缂撳瓨鐨凪ap
-     *
-     * @param key 缂撳瓨鐨勯敭鍊�
-     * @return map瀵硅薄
-     */
-    public static <T> Map<String, T> getCacheMap(final String key) {
-        RMap<String, T> rMap = CLIENT.getMap(key);
-        return rMap.getAll(rMap.keySet());
-    }
-
-    /**
-     * 鑾峰緱缂撳瓨Map鐨刱ey鍒楄〃
-     *
-     * @param key 缂撳瓨鐨勯敭鍊�
-     * @return key鍒楄〃
-     */
-    public static <T> Set<String> getCacheMapKeySet(final String key) {
-        RMap<String, T> rMap = CLIENT.getMap(key);
-        return rMap.keySet();
-    }
-
-    /**
-     * 寰�Hash涓瓨鍏ユ暟鎹�
-     *
-     * @param key   Redis閿�
-     * @param hKey  Hash閿�
-     * @param value 鍊�
-     */
-    public static <T> void setCacheMapValue(final String key, final String hKey, final T value) {
-        RMap<String, T> rMap = CLIENT.getMap(key);
-        rMap.put(hKey, value);
-    }
-
-    /**
-     * 鑾峰彇Hash涓殑鏁版嵁
-     *
-     * @param key  Redis閿�
-     * @param hKey Hash閿�
-     * @return Hash涓殑瀵硅薄
-     */
-    public static <T> T getCacheMapValue(final String key, final String hKey) {
-        RMap<String, T> rMap = CLIENT.getMap(key);
-        return rMap.get(hKey);
-    }
-
-    /**
-     * 鍒犻櫎Hash涓殑鏁版嵁
-     *
-     * @param key  Redis閿�
-     * @param hKey Hash閿�
-     * @return Hash涓殑瀵硅薄
-     */
-    public static <T> T delCacheMapValue(final String key, final String hKey) {
-        RMap<String, T> rMap = CLIENT.getMap(key);
-        return rMap.remove(hKey);
-    }
-
-    /**
-     * 鑾峰彇澶氫釜Hash涓殑鏁版嵁
-     *
-     * @param key   Redis閿�
-     * @param hKeys Hash閿泦鍚�
-     * @return Hash瀵硅薄闆嗗悎
-     */
-    public static <K, V> Map<K, V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
-        RMap<K, V> rMap = CLIENT.getMap(key);
-        return rMap.getAll(hKeys);
-    }
-
-    /**
-     * 璁剧疆鍘熷瓙鍊�
-     *
-     * @param key   Redis閿�
-     * @param value 鍊�
-     */
-    public static void setAtomicValue(String key, long value) {
-        RAtomicLong atomic = CLIENT.getAtomicLong(key);
-        atomic.set(value);
-    }
-
-    /**
-     * 鑾峰彇鍘熷瓙鍊�
-     *
-     * @param key Redis閿�
-     * @return 褰撳墠鍊�
-     */
-    public static long getAtomicValue(String key) {
-        RAtomicLong atomic = CLIENT.getAtomicLong(key);
-        return atomic.get();
-    }
-
-    /**
-     * 閫掑鍘熷瓙鍊�
-     *
-     * @param key Redis閿�
-     * @return 褰撳墠鍊�
-     */
-    public static long incrAtomicValue(String key) {
-        RAtomicLong atomic = CLIENT.getAtomicLong(key);
-        return atomic.incrementAndGet();
-    }
-
-    /**
-     * 閫掑噺鍘熷瓙鍊�
-     *
-     * @param key Redis閿�
-     * @return 褰撳墠鍊�
-     */
-    public static long decrAtomicValue(String key) {
-        RAtomicLong atomic = CLIENT.getAtomicLong(key);
-        return atomic.decrementAndGet();
-    }
-
-    /**
-     * 鑾峰緱缂撳瓨鐨勫熀鏈璞″垪琛�
-     *
-     * @param pattern 瀛楃涓插墠缂�
-     * @return 瀵硅薄鍒楄〃
-     */
-    public static Collection<String> keys(final String pattern) {
-        Stream<String> stream = CLIENT.getKeys().getKeysStreamByPattern(pattern);
-        return stream.collect(Collectors.toList());
-    }
-
-    /**
-     * 鍒犻櫎缂撳瓨鐨勫熀鏈璞″垪琛�
-     *
-     * @param pattern 瀛楃涓插墠缂�
-     */
-    public static void deleteKeys(final String pattern) {
-        CLIENT.getKeys().deleteByPattern(pattern);
-    }
-
-    /**
-     * 妫�鏌edis涓槸鍚﹀瓨鍦╧ey
-     *
-     * @param key 閿�
-     */
-    public static Boolean hasKey(String key) {
-        RKeys rKeys = CLIENT.getKeys();
-        return rKeys.countExists(key) > 0;
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
deleted file mode 100644
index 0e0d7e7..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.ruoyi.common.utils.reflect;
-
-import cn.hutool.core.util.ReflectUtil;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.lang.reflect.Method;
-
-/**
- * 鍙嶅皠宸ュ叿绫�. 鎻愪緵璋冪敤getter/setter鏂规硶, 璁块棶绉佹湁鍙橀噺, 璋冪敤绉佹湁鏂规硶, 鑾峰彇娉涘瀷绫诲瀷Class, 琚獳OP杩囩殑鐪熷疄绫荤瓑宸ュ叿鍑芥暟.
- *
- * @author Lion Li
- */
-@SuppressWarnings("rawtypes")
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class ReflectUtils extends ReflectUtil {
-
-    private static final String SETTER_PREFIX = "set";
-
-    private static final String GETTER_PREFIX = "get";
-
-    /**
-     * 璋冪敤Getter鏂规硶.
-     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
-     */
-    @SuppressWarnings("unchecked")
-    public static <E> E invokeGetter(Object obj, String propertyName) {
-        Object object = obj;
-        for (String name : StringUtils.split(propertyName, ".")) {
-            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
-            object = invoke(object, getterMethodName);
-        }
-        return (E) object;
-    }
-
-    /**
-     * 璋冪敤Setter鏂规硶, 浠呭尮閰嶆柟娉曞悕銆�
-     * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
-     */
-    public static <E> void invokeSetter(Object obj, String propertyName, E value) {
-        Object object = obj;
-        String[] names = StringUtils.split(propertyName, ".");
-        for (int i = 0; i < names.length; i++) {
-            if (i < names.length - 1) {
-                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
-                object = invoke(object, getterMethodName);
-            } else {
-                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
-                Method method = getMethodByName(object.getClass(), setterMethodName);
-                invoke(object, method, value);
-            }
-        }
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java
deleted file mode 100644
index 8b37e41..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.ruoyi.common.utils.spring;
-
-import cn.hutool.extra.spring.SpringUtil;
-import org.springframework.aop.framework.AopContext;
-import org.springframework.beans.factory.NoSuchBeanDefinitionException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.stereotype.Component;
-
-/**
- * spring宸ュ叿绫�
- *
- * @author Lion Li
- */
-@Component
-public final class SpringUtils extends SpringUtil {
-
-    /**
-     * 濡傛灉BeanFactory鍖呭惈涓�涓笌鎵�缁欏悕绉板尮閰嶇殑bean瀹氫箟锛屽垯杩斿洖true
-     *
-     * @param name
-     * @return boolean
-     */
-    public static boolean containsBean(String name) {
-        return getBeanFactory().containsBean(name);
-    }
-
-    /**
-     * 鍒ゆ柇浠ョ粰瀹氬悕瀛楁敞鍐岀殑bean瀹氫箟鏄竴涓猻ingleton杩樻槸涓�涓猵rototype銆�
-     * 濡傛灉涓庣粰瀹氬悕瀛楃浉搴旂殑bean瀹氫箟娌℃湁琚壘鍒帮紝灏嗕細鎶涘嚭涓�涓紓甯革紙NoSuchBeanDefinitionException锛�
-     *
-     * @param name
-     * @return boolean
-     */
-    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
-        return getBeanFactory().isSingleton(name);
-    }
-
-    /**
-     * @param name
-     * @return Class 娉ㄥ唽瀵硅薄鐨勭被鍨�
-     */
-    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
-        return getBeanFactory().getType(name);
-    }
-
-    /**
-     * 濡傛灉缁欏畾鐨刡ean鍚嶅瓧鍦╞ean瀹氫箟涓湁鍒悕锛屽垯杩斿洖杩欎簺鍒悕
-     *
-     * @param name
-     */
-    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
-        return getBeanFactory().getAliases(name);
-    }
-
-    /**
-     * 鑾峰彇aop浠g悊瀵硅薄
-     *
-     * @param invoker
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    public static <T> T getAopProxy(T invoker) {
-        return (T) AopContext.currentProxy();
-    }
-
-
-    /**
-     * 鑾峰彇spring涓婁笅鏂�
-     */
-    public static ApplicationContext context() {
-        return getApplicationContext();
-    }
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
deleted file mode 100644
index 7891496..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.ruoyi.common.utils.sql;
-
-import com.ruoyi.common.exception.UtilException;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-/**
- * sql鎿嶄綔宸ュ叿绫�
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class SqlUtil {
-
-    /**
-     * 瀹氫箟甯哥敤鐨� sql鍏抽敭瀛�
-     */
-    public static final String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
-
-    /**
-     * 浠呮敮鎸佸瓧姣嶃�佹暟瀛椼�佷笅鍒掔嚎銆佺┖鏍笺�侀�楀彿銆佸皬鏁扮偣锛堟敮鎸佸涓瓧娈垫帓搴忥級
-     */
-    public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
-
-    /**
-     * 妫�鏌ュ瓧绗︼紝闃叉娉ㄥ叆缁曡繃
-     */
-    public static String escapeOrderBySql(String value) {
-        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
-            throw new UtilException("鍙傛暟涓嶇鍚堣鑼冿紝涓嶈兘杩涜鏌ヨ");
-        }
-        return value;
-    }
-
-    /**
-     * 楠岃瘉 order by 璇硶鏄惁绗﹀悎瑙勮寖
-     */
-    public static boolean isValidOrderBySql(String value) {
-        return value.matches(SQL_PATTERN);
-    }
-
-    /**
-     * SQL鍏抽敭瀛楁鏌�
-     */
-    public static void filterKeyword(String value) {
-        if (StringUtils.isEmpty(value)) {
-            return;
-        }
-        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
-        for (String sqlKeyword : sqlKeywords) {
-            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) {
-                throw new UtilException("鍙傛暟瀛樺湪SQL娉ㄥ叆椋庨櫓");
-            }
-        }
-    }
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
deleted file mode 100644
index 315d29c..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.common.xss;
-
-import jakarta.validation.Constraint;
-import jakarta.validation.Payload;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 鑷畾涔墄ss鏍¢獙娉ㄨВ
- *
- * @author Lion Li
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
-@Constraint(validatedBy = {XssValidator.class})
-public @interface Xss {
-
-    String message() default "涓嶅厑璁镐换浣曡剼鏈繍琛�";
-
-    Class<?>[] groups() default {};
-
-    Class<? extends Payload>[] payload() default {};
-
-}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
deleted file mode 100644
index e9e02c0..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ruoyi.common.xss;
-
-import cn.hutool.core.util.ReUtil;
-import cn.hutool.http.HtmlUtil;
-
-import jakarta.validation.ConstraintValidator;
-import jakarta.validation.ConstraintValidatorContext;
-
-/**
- * 鑷畾涔墄ss鏍¢獙娉ㄨВ瀹炵幇
- *
- * @author Lion Li
- */
-public class XssValidator implements ConstraintValidator<Xss, String> {
-
-    @Override
-    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
-        return !ReUtil.contains(HtmlUtil.RE_HTML_MARK, value);
-    }
-
-}
diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml
deleted file mode 100644
index 869241b..0000000
--- a/ruoyi-demo/pom.xml
+++ /dev/null
@@ -1,45 +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>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-demo</artifactId>
-
-    <description>
-        demo妯″潡
-    </description>
-
-    <dependencies>
-
-        <!-- 閫氱敤宸ュ叿-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-sms</artifactId>
-        </dependency>
-
-        <!-- 鐭俊 鐢ㄥ摢涓鍏ュ摢涓緷璧� -->
-<!--        <dependency>-->
-<!--            <groupId>com.aliyun</groupId>-->
-<!--            <artifactId>dysmsapi20170525</artifactId>-->
-<!--        </dependency>-->
-
-<!--        <dependency>-->
-<!--            <groupId>com.tencentcloudapi</groupId>-->
-<!--            <artifactId>tencentcloud-sdk-java-sms</artifactId>-->
-<!--        </dependency>-->
-
-    </dependencies>
-
-</project>
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java
deleted file mode 100644
index 6db4dc4..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.email.MailUtils;
-import lombok.RequiredArgsConstructor;
-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 java.io.File;
-
-
-/**
- * 閭欢鍙戦�佹渚�
- *
- * @author Michelle.Chung
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/mail")
-public class MailController {
-
-    /**
-     * 鍙戦�侀偖浠�
-     *
-     * @param to      鎺ユ敹浜�
-     * @param subject 鏍囬
-     * @param text    鍐呭
-     */
-    @GetMapping("/sendSimpleMessage")
-    public R<Void> sendSimpleMessage(String to, String subject, String text) {
-        MailUtils.sendText(to, subject, text);
-        return R.ok();
-    }
-
-    /**
-     * 鍙戦�侀偖浠讹紙甯﹂檮浠讹級
-     *
-     * @param to       鎺ユ敹浜�
-     * @param subject  鏍囬
-     * @param text     鍐呭
-     * @param filePath 闄勪欢璺緞
-     */
-    @GetMapping("/sendMessageWithAttachment")
-    public R<Void> sendMessageWithAttachment(String to, String subject, String text, String filePath) {
-        MailUtils.sendText(to, subject, text, new File(filePath));
-        return R.ok();
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java
deleted file mode 100644
index 7342cba..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import lombok.RequiredArgsConstructor;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.time.Duration;
-
-/**
- * spring-cache 婕旂ず妗堜緥
- *
- * @author Lion Li
- */
-// 绫荤骇鍒� 缂撳瓨缁熶竴閰嶇疆
-//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE)
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/cache")
-public class RedisCacheController {
-
-    /**
-     * 娴嬭瘯 @Cacheable
-     * <p>
-     * 琛ㄧず杩欎釜鏂规硶鏈変簡缂撳瓨鐨勫姛鑳�,鏂规硶鐨勮繑鍥炲�间細琚紦瀛樹笅鏉�
-     * 涓嬩竴娆¤皟鐢ㄨ鏂规硶鍓�,浼氬幓妫�鏌ユ槸鍚︾紦瀛樹腑宸茬粡鏈夊��
-     * 濡傛灉鏈夊氨鐩存帴杩斿洖,涓嶈皟鐢ㄦ柟娉�
-     * 濡傛灉娌℃湁,灏辫皟鐢ㄦ柟娉�,鐒跺悗鎶婄粨鏋滅紦瀛樿捣鏉�
-     * 杩欎釜娉ㄨВ銆屼竴鑸敤鍦ㄦ煡璇㈡柟娉曚笂銆�
-     * <p>
-     * 閲嶇偣璇存槑: 缂撳瓨娉ㄨВ涓ヨ皑涓庡叾浠栫瓫閫夋暟鎹姛鑳戒竴璧蜂娇鐢�
-     * 渚嬪: 鏁版嵁鏉冮檺娉ㄨВ 浼氶�犳垚 缂撳瓨鍑荤┛ 涓� 鏁版嵁涓嶄竴鑷撮棶棰�
-     * <p>
-     * cacheNames 鍛藉悕瑙勫垯 鏌ョ湅 {@link CacheNames} 娉ㄩ噴 鏀寔澶氬弬鏁�
-     */
-    @Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null")
-    @GetMapping("/test1")
-    public R<String> test1(String key, String value) {
-        return R.ok("鎿嶄綔鎴愬姛", value);
-    }
-
-    /**
-     * 娴嬭瘯 @CachePut
-     * <p>
-     * 鍔犱簡@CachePut娉ㄨВ鐨勬柟娉�,浼氭妸鏂规硶鐨勮繑鍥炲�紁ut鍒扮紦瀛橀噷闈㈢紦瀛樿捣鏉�,渚涘叾瀹冨湴鏂逛娇鐢�
-     * 瀹冦�岄�氬父鐢ㄥ湪鏂板鎴栬�呭疄鏃舵洿鏂版柟娉曚笂銆�
-     * <p>
-     * cacheNames 鍛藉悕瑙勫垯 鏌ョ湅 {@link CacheNames} 娉ㄩ噴 鏀寔澶氬弬鏁�
-     */
-    @CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
-    @GetMapping("/test2")
-    public R<String> test2(String key, String value) {
-        return R.ok("鎿嶄綔鎴愬姛", value);
-    }
-
-    /**
-     * 娴嬭瘯 @CacheEvict
-     * <p>
-     * 浣跨敤浜咰acheEvict娉ㄨВ鐨勬柟娉�,浼氭竻绌烘寚瀹氱紦瀛�
-     * 銆屼竴鑸敤鍦ㄥ垹闄ょ殑鏂规硶涓娿��
-     * <p>
-     * cacheNames 鍛藉悕瑙勫垯 鏌ョ湅 {@link CacheNames} 娉ㄩ噴 鏀寔澶氬弬鏁�
-     */
-    @CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
-    @GetMapping("/test3")
-    public R<String> test3(String key, String value) {
-        return R.ok("鎿嶄綔鎴愬姛", value);
-    }
-
-    /**
-     * 娴嬭瘯璁剧疆杩囨湡鏃堕棿
-     * 鎵嬪姩璁剧疆杩囨湡鏃堕棿10绉�
-     * 11绉掑悗鑾峰彇 鍒ゆ柇鏄惁鐩哥瓑
-     */
-    @GetMapping("/test6")
-    public R<Boolean> test6(String key, String value) {
-        RedisUtils.setCacheObject(key, value);
-        boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10));
-        System.out.println("***********" + flag);
-        try {
-            Thread.sleep(11 * 1000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        Object obj = RedisUtils.getCacheObject(key);
-        return R.ok(value.equals(obj));
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java
deleted file mode 100644
index 0c2af39..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * Redis 鍙戝竷璁㈤槄 婕旂ず妗堜緥
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/redis/pubsub")
-public class RedisPubSubController {
-
-    /**
-     * 鍙戝竷娑堟伅
-     *
-     * @param key   閫氶亾Key
-     * @param value 鍙戦�佸唴瀹�
-     */
-    @GetMapping("/pub")
-    public R<Void> pub(String key, String value) {
-        RedisUtils.publish(key, value, consumer -> {
-            System.out.println("鍙戝竷閫氶亾 => " + key + ", 鍙戦�佸�� => " + value);
-        });
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 璁㈤槄娑堟伅
-     *
-     * @param key 閫氶亾Key
-     */
-    @GetMapping("/sub")
-    public R<Void> sub(String key) {
-        RedisUtils.subscribe(key, String.class, msg -> {
-            System.out.println("璁㈤槄閫氶亾 => " + key + ", 鎺ユ敹鍊� => " + msg);
-        });
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java
deleted file mode 100644
index ee2e530..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.annotation.RateLimiter;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.enums.LimitType;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-
-/**
- * 娴嬭瘯鍒嗗竷寮忛檺娴佹牱渚�
- *
- * @author Lion Li
- */
-@Slf4j
-@RestController
-@RequestMapping("/demo/rateLimiter")
-public class RedisRateLimiterController {
-
-    /**
-     * 娴嬭瘯鍏ㄥ眬闄愭祦
-     * 鍏ㄥ眬褰卞搷
-     */
-    @RateLimiter(count = 2, time = 10)
-    @GetMapping("/test")
-    public R<String> test(String value) {
-        return R.ok("鎿嶄綔鎴愬姛", value);
-    }
-
-    /**
-     * 娴嬭瘯璇锋眰IP闄愭祦
-     * 鍚屼竴IP璇锋眰鍙楀奖鍝�
-     */
-    @RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
-    @GetMapping("/testip")
-    public R<String> testip(String value) {
-        return R.ok("鎿嶄綔鎴愬姛", value);
-    }
-
-    /**
-     * 娴嬭瘯闆嗙兢瀹炰緥闄愭祦
-     * 鍚姩涓や釜鍚庣鏈嶅姟浜掍笉褰卞搷
-     */
-    @RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
-    @GetMapping("/testcluster")
-    public R<String> testcluster(String value) {
-        return R.ok("鎿嶄綔鎴愬姛", value);
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java
deleted file mode 100644
index cc6012f..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.sms.config.properties.SmsProperties;
-import com.ruoyi.sms.core.SmsTemplate;
-import lombok.RequiredArgsConstructor;
-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 java.util.HashMap;
-import java.util.Map;
-
-/**
- * 鐭俊婕旂ず妗堜緥
- * 璇峰厛闃呰鏂囨。 鍚﹀垯鏃犳硶浣跨敤
- *
- * @author Lion Li
- * @version 4.2.0
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/sms")
-public class SmsController {
-
-    private final SmsProperties smsProperties;
-//    private final SmsTemplate smsTemplate; // 鍙互浣跨敤spring娉ㄥ叆
-//    private final AliyunSmsTemplate smsTemplate; // 涔熷彲浠ユ敞鍏ユ煇涓巶瀹剁殑妯℃澘宸ュ叿
-
-    /**
-     * 鍙戦�佺煭淇liyun
-     *
-     * @param phones     鐢佃瘽鍙�
-     * @param templateId 妯℃澘ID
-     */
-    @GetMapping("/sendAliyun")
-    public R<Object> sendAliyun(String phones, String templateId) {
-        if (!smsProperties.getEnabled()) {
-            return R.fail("褰撳墠绯荤粺娌℃湁寮�鍚煭淇″姛鑳斤紒");
-        }
-        if (!SpringUtils.containsBean("aliyunSmsTemplate")) {
-            return R.fail("闃块噷浜戜緷璧栨湭寮曞叆锛�");
-        }
-        SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
-        Map<String, String> map = new HashMap<>(1);
-        map.put("code", "1234");
-        Object send = smsTemplate.send(phones, templateId, map);
-        return R.ok(send);
-    }
-
-    /**
-     * 鍙戦�佺煭淇encent
-     *
-     * @param phones     鐢佃瘽鍙�
-     * @param templateId 妯℃澘ID
-     */
-    @GetMapping("/sendTencent")
-    public R<Object> sendTencent(String phones, String templateId) {
-        if (!smsProperties.getEnabled()) {
-            return R.fail("褰撳墠绯荤粺娌℃湁寮�鍚煭淇″姛鑳斤紒");
-        }
-        if (!SpringUtils.containsBean("tencentSmsTemplate")) {
-            return R.fail("鑵捐浜戜緷璧栨湭寮曞叆锛�");
-        }
-        SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
-        Map<String, String> map = new HashMap<>(1);
-//        map.put("2", "娴嬭瘯娴嬭瘯");
-        map.put("1", "1234");
-        Object send = smsTemplate.send(phones, templateId, map);
-        return R.ok(send);
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
deleted file mode 100644
index 3bd2867..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.demo.domain.TestDemo;
-import com.ruoyi.demo.mapper.TestDemoMapper;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 娴嬭瘯鎵归噺鏂规硶
- *
- * @author Lion Li
- * @date 2021-05-30
- */
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/batch")
-public class TestBatchController extends BaseController {
-
-    /**
-     * 涓轰簡渚夸簬娴嬭瘯 鐩存帴寮曞叆mapper
-     */
-    private final TestDemoMapper testDemoMapper;
-
-    /**
-     * 鏂板鎵归噺鏂规硶 鍙畬缇庢浛浠� saveBatch 绉掔骇鎻掑叆涓婁竾鏁版嵁 (瀵筸ysql璐熻嵎杈冨ぇ)
-     * <p>
-     * 3.5.0 鐗堟湰 澧炲姞 rewriteBatchedStatements=true 鎵瑰鐞嗗弬鏁� 浣� MP 鍘熺敓鎵瑰鐞嗗彲浠ヨ揪鍒板悓鏍风殑閫熷害
-     */
-    @PostMapping("/add")
-//    @DS("slave")
-    public R<Void> add() {
-        List<TestDemo> list = new ArrayList<>();
-        for (int i = 0; i < 1000; i++) {
-            TestDemo testDemo = new TestDemo();
-            testDemo.setOrderNum(-1);
-            testDemo.setTestKey("鎵归噺鏂板");
-            testDemo.setValue("娴嬭瘯鏂板");
-            list.add(testDemo);
-        }
-        return toAjax(testDemoMapper.insertBatch(list));
-    }
-
-    /**
-     * 鏂板鎴栨洿鏂� 鍙畬缇庢浛浠� saveOrUpdateBatch 楂樻�ц兘
-     * <p>
-     * 3.5.0 鐗堟湰 澧炲姞 rewriteBatchedStatements=true 鎵瑰鐞嗗弬鏁� 浣� MP 鍘熺敓鎵瑰鐞嗗彲浠ヨ揪鍒板悓鏍风殑閫熷害
-     */
-    @PostMapping("/addOrUpdate")
-//    @DS("slave")
-    public R<Void> addOrUpdate() {
-        List<TestDemo> list = new ArrayList<>();
-        for (int i = 0; i < 1000; i++) {
-            TestDemo testDemo = new TestDemo();
-            testDemo.setOrderNum(-1);
-            testDemo.setTestKey("鎵归噺鏂板");
-            testDemo.setValue("娴嬭瘯鏂板");
-            list.add(testDemo);
-        }
-        testDemoMapper.insertBatch(list);
-        for (int i = 0; i < list.size(); i++) {
-            TestDemo testDemo = list.get(i);
-            testDemo.setTestKey("鎵归噺鏂板鎴栦慨鏀�");
-            testDemo.setValue("鎵归噺鏂板鎴栦慨鏀�");
-            if (i % 2 == 0) {
-                testDemo.setId(null);
-            }
-        }
-        return toAjax(testDemoMapper.insertOrUpdateBatch(list));
-    }
-
-    /**
-     * 鍒犻櫎鎵归噺鏂规硶
-     */
-    @DeleteMapping()
-//    @DS("slave")
-    public R<Void> remove() {
-        return toAjax(testDemoMapper.delete(new LambdaQueryWrapper<TestDemo>()
-            .eq(TestDemo::getOrderNum, -1L)));
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
deleted file mode 100644
index 7c9a365..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.bean.BeanUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.annotation.RepeatSubmit;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import com.ruoyi.common.core.validate.QueryGroup;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.excel.ExcelResult;
-import com.ruoyi.common.utils.ValidatorUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.demo.domain.TestDemo;
-import com.ruoyi.demo.domain.bo.TestDemoBo;
-import com.ruoyi.demo.domain.bo.TestDemoImportVo;
-import com.ruoyi.demo.domain.vo.TestDemoVo;
-import com.ruoyi.demo.service.ITestDemoService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.MediaType;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 娴嬭瘯鍗曡〃Controller
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/demo")
-public class TestDemoController extends BaseController {
-
-    private final ITestDemoService iTestDemoService;
-
-    /**
-     * 鏌ヨ娴嬭瘯鍗曡〃鍒楄〃
-     */
-    @SaCheckPermission("demo:demo:list")
-    @GetMapping("/list")
-    public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
-        return iTestDemoService.queryPageList(bo, pageQuery);
-    }
-
-    /**
-     * 鑷畾涔夊垎椤垫煡璇�
-     */
-    @SaCheckPermission("demo:demo:list")
-    @GetMapping("/page")
-    public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
-        return iTestDemoService.customPageList(bo, pageQuery);
-    }
-
-    /**
-     * 瀵煎叆鏁版嵁
-     *
-     * @param file 瀵煎叆鏂囦欢
-     */
-    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.IMPORT)
-    @SaCheckPermission("demo:demo:import")
-    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
-        ExcelResult<TestDemoImportVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true);
-        List<TestDemoImportVo> volist = excelResult.getList();
-        List<TestDemo> list = BeanUtil.copyToList(volist, TestDemo.class);
-        iTestDemoService.saveBatch(list);
-        return R.ok(excelResult.getAnalysis());
-    }
-
-    /**
-     * 瀵煎嚭娴嬭瘯鍗曡〃鍒楄〃
-     */
-    @SaCheckPermission("demo:demo:export")
-    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.EXPORT)
-    @PostMapping("/export")
-    public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
-        List<TestDemoVo> list = iTestDemoService.queryList(bo);
-        // 娴嬭瘯闆姳id瀵煎嚭
-//        for (TestDemoVo vo : list) {
-//            vo.setId(1234567891234567893L);
-//        }
-        ExcelUtil.exportExcel(list, "娴嬭瘯鍗曡〃", TestDemoVo.class, response);
-    }
-
-    /**
-     * 鑾峰彇娴嬭瘯鍗曡〃璇︾粏淇℃伅
-     *
-     * @param id 娴嬭瘯ID
-     */
-    @SaCheckPermission("demo:demo:query")
-    @GetMapping("/{id}")
-    public R<TestDemoVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
-                                 @PathVariable("id") Long id) {
-        return R.ok(iTestDemoService.queryById(id));
-    }
-
-    /**
-     * 鏂板娴嬭瘯鍗曡〃
-     */
-    @SaCheckPermission("demo:demo:add")
-    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.INSERT)
-    @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}")
-    @PostMapping()
-    public R<Void> add(@RequestBody TestDemoBo bo) {
-        // 浣跨敤鏍¢獙宸ュ叿瀵规爣 @Validated(AddGroup.class) 娉ㄨВ
-        // 鐢ㄤ簬鍦ㄩ潪 Controller 鐨勫湴鏂规牎楠屽璞�
-        ValidatorUtils.validate(bo, AddGroup.class);
-        return toAjax(iTestDemoService.insertByBo(bo));
-    }
-
-    /**
-     * 淇敼娴嬭瘯鍗曡〃
-     */
-    @SaCheckPermission("demo:demo:edit")
-    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.UPDATE)
-    @RepeatSubmit
-    @PutMapping()
-    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
-        return toAjax(iTestDemoService.updateByBo(bo));
-    }
-
-    /**
-     * 鍒犻櫎娴嬭瘯鍗曡〃
-     *
-     * @param ids 娴嬭瘯ID涓�
-     */
-    @SaCheckPermission("demo:demo:remove")
-    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ids}")
-    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
-                          @PathVariable Long[] ids) {
-        return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true));
-    }
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java
deleted file mode 100644
index 2bce8a7..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import cn.hutool.core.collection.CollUtil;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 娴嬭瘯Excel鍔熻兘
- *
- * @author Lion Li
- */
-@RestController
-@RequestMapping("/demo/excel")
-public class TestExcelController {
-
-    /**
-     * 鍗曞垪琛ㄥ鏁版嵁
-     */
-    @GetMapping("/exportTemplateOne")
-    public void exportTemplateOne(HttpServletResponse response) {
-        Map<String, String> map = new HashMap<>();
-        map.put("title", "鍗曞垪琛ㄥ鏁版嵁");
-        map.put("test1", "鏁版嵁娴嬭瘯1");
-        map.put("test2", "鏁版嵁娴嬭瘯2");
-        map.put("test3", "鏁版嵁娴嬭瘯3");
-        map.put("test4", "鏁版嵁娴嬭瘯4");
-        map.put("testTest", "666");
-        List<TestObj> list = new ArrayList<>();
-        list.add(new TestObj("鍗曞垪琛ㄦ祴璇�1", "鍒楄〃娴嬭瘯1", "鍒楄〃娴嬭瘯2", "鍒楄〃娴嬭瘯3", "鍒楄〃娴嬭瘯4"));
-        list.add(new TestObj("鍗曞垪琛ㄦ祴璇�2", "鍒楄〃娴嬭瘯5", "鍒楄〃娴嬭瘯6", "鍒楄〃娴嬭瘯7", "鍒楄〃娴嬭瘯8"));
-        list.add(new TestObj("鍗曞垪琛ㄦ祴璇�3", "鍒楄〃娴嬭瘯9", "鍒楄〃娴嬭瘯10", "鍒楄〃娴嬭瘯11", "鍒楄〃娴嬭瘯12"));
-        ExcelUtil.exportTemplate(CollUtil.newArrayList(map, list), "鍗曞垪琛�.xlsx", "excel/鍗曞垪琛�.xlsx", response);
-    }
-
-    /**
-     * 澶氬垪琛ㄥ鏁版嵁
-     */
-    @GetMapping("/exportTemplateMuliti")
-    public void exportTemplateMuliti(HttpServletResponse response) {
-        Map<String, String> map = new HashMap<>();
-        map.put("title1", "鏍囬1");
-        map.put("title2", "鏍囬2");
-        map.put("title3", "鏍囬3");
-        map.put("title4", "鏍囬4");
-        map.put("author", "Lion Li");
-        List<TestObj1> list1 = new ArrayList<>();
-        list1.add(new TestObj1("list1娴嬭瘯1", "list1娴嬭瘯2", "list1娴嬭瘯3"));
-        list1.add(new TestObj1("list1娴嬭瘯4", "list1娴嬭瘯5", "list1娴嬭瘯6"));
-        list1.add(new TestObj1("list1娴嬭瘯7", "list1娴嬭瘯8", "list1娴嬭瘯9"));
-        List<TestObj1> list2 = new ArrayList<>();
-        list2.add(new TestObj1("list2娴嬭瘯1", "list2娴嬭瘯2", "list2娴嬭瘯3"));
-        list2.add(new TestObj1("list2娴嬭瘯4", "list2娴嬭瘯5", "list2娴嬭瘯6"));
-        List<TestObj1> list3 = new ArrayList<>();
-        list3.add(new TestObj1("list3娴嬭瘯1", "list3娴嬭瘯2", "list3娴嬭瘯3"));
-        List<TestObj1> list4 = new ArrayList<>();
-        list4.add(new TestObj1("list4娴嬭瘯1", "list4娴嬭瘯2", "list4娴嬭瘯3"));
-        list4.add(new TestObj1("list4娴嬭瘯4", "list4娴嬭瘯5", "list4娴嬭瘯6"));
-        list4.add(new TestObj1("list4娴嬭瘯7", "list4娴嬭瘯8", "list4娴嬭瘯9"));
-        list4.add(new TestObj1("list4娴嬭瘯10", "list4娴嬭瘯11", "list4娴嬭瘯12"));
-        Map<String, Object> multiListMap = new HashMap<>();
-        multiListMap.put("map", map);
-        multiListMap.put("data1", list1);
-        multiListMap.put("data2", list2);
-        multiListMap.put("data3", list3);
-        multiListMap.put("data4", list4);
-        ExcelUtil.exportTemplateMultiList(multiListMap, "澶氬垪琛�.xlsx", "excel/澶氬垪琛�.xlsx", response);
-    }
-
-    @Data
-    @AllArgsConstructor
-    static class TestObj1 {
-        private String test1;
-        private String test2;
-        private String test3;
-    }
-
-    @Data
-    @AllArgsConstructor
-    static class TestObj {
-        private String name;
-        private String list1;
-        private String list2;
-        private String list3;
-        private String list4;
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java
deleted file mode 100644
index c6fa799..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.MessageUtils;
-import lombok.Data;
-import org.hibernate.validator.constraints.Range;
-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 jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-
-/**
- * 娴嬭瘯鍥介檯鍖�
- *
- * @author Lion Li
- */
-@Validated
-@RestController
-@RequestMapping("/demo/i18n")
-public class TestI18nController {
-
-    /**
-     * 閫氳繃code鑾峰彇鍥介檯鍖栧唴瀹�
-     * code涓� messages.properties 涓殑 key
-     * <p>
-     * 娴嬭瘯浣跨敤 user.register.success
-     *
-     * @param code 鍥介檯鍖朿ode
-     */
-    @GetMapping()
-    public R<Void> get(String code) {
-        return R.ok(MessageUtils.message(code));
-    }
-
-    /**
-     * Validator 鏍¢獙鍥介檯鍖�
-     * 涓嶄紶鍊� 鍒嗗埆鏌ョ湅寮傚父杩斿洖
-     * <p>
-     * 娴嬭瘯浣跨敤 not.null
-     */
-    @GetMapping("/test1")
-    public R<Void> test1(@NotBlank(message = "{not.null}") String str) {
-        return R.ok(str);
-    }
-
-    /**
-     * Bean 鏍¢獙鍥介檯鍖�
-     * 涓嶄紶鍊� 鍒嗗埆鏌ョ湅寮傚父杩斿洖
-     * <p>
-     * 娴嬭瘯浣跨敤 not.null
-     */
-    @GetMapping("/test2")
-    public R<TestI18nBo> test2(@Validated TestI18nBo bo) {
-        return R.ok(bo);
-    }
-
-    @Data
-    public static class TestI18nBo {
-
-        @NotBlank(message = "{not.null}")
-        private String name;
-
-        @NotNull(message = "{not.null}")
-        @Range(min = 0, max = 100, message = "{length.not.valid}")
-        private Integer age;
-    }
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java
deleted file mode 100644
index 6bf904c..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import com.ruoyi.common.annotation.Sensitive;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.enums.SensitiveStrategy;
-import lombok.Data;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 娴嬭瘯鏁版嵁鑴辨晱鎺у埗鍣�
- * <p>
- * 榛樿绠$悊鍛樹笉杩囨护
- * 闇�鑷鏍规嵁涓氬姟閲嶅啓瀹炵幇
- *
- * @author Lion Li
- * @version 3.6.0
- * @see com.ruoyi.common.core.service.SensitiveService
- */
-@RestController
-@RequestMapping("/demo/sensitive")
-public class TestSensitiveController extends BaseController {
-
-    /**
-     * 娴嬭瘯鏁版嵁鑴辨晱
-     */
-    @GetMapping("/test")
-    public R<TestSensitive> test() {
-        TestSensitive testSensitive = new TestSensitive();
-        testSensitive.setIdCard("210397198608215431");
-        testSensitive.setPhone("17640125371");
-        testSensitive.setAddress("鍖椾含甯傛湞闃冲尯鏌愭煇鍥涘悎闄�1203瀹�");
-        testSensitive.setEmail("17640125371@163.com");
-        testSensitive.setBankCard("6226456952351452853");
-        return R.ok(testSensitive);
-    }
-
-    @Data
-    static class TestSensitive {
-
-        /**
-         * 韬唤璇�
-         */
-        @Sensitive(strategy = SensitiveStrategy.ID_CARD)
-        private String idCard;
-
-        /**
-         * 鐢佃瘽
-         */
-        @Sensitive(strategy = SensitiveStrategy.PHONE)
-        private String phone;
-
-        /**
-         * 鍦板潃
-         */
-        @Sensitive(strategy = SensitiveStrategy.ADDRESS)
-        private String address;
-
-        /**
-         * 閭
-         */
-        @Sensitive(strategy = SensitiveStrategy.EMAIL)
-        private String email;
-
-        /**
-         * 閾惰鍗�
-         */
-        @Sensitive(strategy = SensitiveStrategy.BANK_CARD)
-        private String bankCard;
-
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
deleted file mode 100644
index e6ed0bb..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.ruoyi.demo.controller;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.annotation.RepeatSubmit;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import com.ruoyi.common.core.validate.QueryGroup;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.demo.domain.bo.TestTreeBo;
-import com.ruoyi.demo.domain.vo.TestTreeVo;
-import com.ruoyi.demo.service.ITestTreeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 娴嬭瘯鏍戣〃Controller
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/tree")
-public class TestTreeController extends BaseController {
-
-    private final ITestTreeService iTestTreeService;
-
-    /**
-     * 鏌ヨ娴嬭瘯鏍戣〃鍒楄〃
-     */
-    @SaCheckPermission("demo:tree:list")
-    @GetMapping("/list")
-    public R<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) {
-        List<TestTreeVo> list = iTestTreeService.queryList(bo);
-        return R.ok(list);
-    }
-
-    /**
-     * 瀵煎嚭娴嬭瘯鏍戣〃鍒楄〃
-     */
-    @SaCheckPermission("demo:tree:export")
-    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public void export(@Validated TestTreeBo bo, HttpServletResponse response) {
-        List<TestTreeVo> list = iTestTreeService.queryList(bo);
-        ExcelUtil.exportExcel(list, "娴嬭瘯鏍戣〃", TestTreeVo.class, response);
-    }
-
-    /**
-     * 鑾峰彇娴嬭瘯鏍戣〃璇︾粏淇℃伅
-     *
-     * @param id 娴嬭瘯鏍慖D
-     */
-    @SaCheckPermission("demo:tree:query")
-    @GetMapping("/{id}")
-    public R<TestTreeVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
-                                 @PathVariable("id") Long id) {
-        return R.ok(iTestTreeService.queryById(id));
-    }
-
-    /**
-     * 鏂板娴嬭瘯鏍戣〃
-     */
-    @SaCheckPermission("demo:tree:add")
-    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.INSERT)
-    @RepeatSubmit
-    @PostMapping()
-    public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
-        return toAjax(iTestTreeService.insertByBo(bo));
-    }
-
-    /**
-     * 淇敼娴嬭瘯鏍戣〃
-     */
-    @SaCheckPermission("demo:tree:edit")
-    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.UPDATE)
-    @RepeatSubmit
-    @PutMapping()
-    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
-        return toAjax(iTestTreeService.updateByBo(bo));
-    }
-
-    /**
-     * 鍒犻櫎娴嬭瘯鏍戣〃
-     *
-     * @param ids 娴嬭瘯鏍慖D涓�
-     */
-    @SaCheckPermission("demo:tree:remove")
-    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ids}")
-    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
-                          @PathVariable Long[] ids) {
-        return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true));
-    }
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java
deleted file mode 100644
index 968a419..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.demo.controller.queue;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.redis.QueueUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 鏈夌晫闃熷垪 婕旂ず妗堜緥
- * <p>
- * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
- * <p>
- * 闆嗙兢娴嬭瘯閫氳繃 鍚屼竴涓暟鎹彧浼氳娑堣垂涓�娆� 鍋氬ソ浜嬪姟琛ュ伩
- * 闆嗙兢娴嬭瘯娴佺▼ 鍦ㄥ叾涓竴鍙板彂閫佹暟鎹� 涓ょ鍒嗗埆璋冪敤鑾峰彇鎺ュ彛 涓�娆¤幏鍙栦竴鏉�
- *
- * @author Lion Li
- * @version 3.6.0
- */
-@Slf4j
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/queue/bounded")
-public class BoundedQueueController {
-
-
-    /**
-     * 娣诲姞闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param capacity  瀹归噺
-     */
-    @GetMapping("/add")
-    public R<Void> add(String queueName, int capacity) {
-        // 鐢ㄥ畬浜嗕竴瀹氳閿�姣� 鍚﹀垯浼氫竴鐩村瓨鍦�
-        boolean b = QueueUtils.destroyQueue(queueName);
-        log.info("閫氶亾: {} , 鍒犻櫎: {}", queueName, b);
-        // 鍒濆鍖栬缃竴娆″嵆鍙�
-        if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) {
-            log.info("閫氶亾: {} , 璁剧疆瀹归噺: {}", queueName, capacity);
-        } else {
-            log.info("閫氶亾: {} , 璁剧疆瀹归噺澶辫触", queueName);
-            return R.fail("鎿嶄綔澶辫触");
-        }
-        for (int i = 0; i < 11; i++) {
-            String data = "data-" + i;
-            boolean flag = QueueUtils.addBoundedQueueObject(queueName, data);
-            if (flag == false) {
-                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {} 澶辫触, 閫氶亾宸叉弧", queueName, data);
-            } else {
-                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}", queueName, data);
-            }
-        }
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 鍒犻櫎闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    @GetMapping("/remove")
-    public R<Void> remove(String queueName) {
-        String data = "data-" + 5;
-        if (QueueUtils.removeQueueObject(queueName, data)) {
-            log.info("閫氶亾: {} , 鍒犻櫎鏁版嵁: {}", queueName, data);
-        } else {
-            return R.fail("鎿嶄綔澶辫触");
-        }
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 鑾峰彇闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    @GetMapping("/get")
-    public R<Void> get(String queueName) {
-        String data;
-        do {
-            data = QueueUtils.getQueueObject(queueName);
-            log.info("閫氶亾: {} , 鑾峰彇鏁版嵁: {}", queueName, data);
-        } while (data != null);
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java
deleted file mode 100644
index e6dbee8..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.demo.controller.queue;
-
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.redis.QueueUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * 寤惰繜闃熷垪 婕旂ず妗堜緥
- * <p>
- * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
- * 渚嬪: 鍒涘缓璁㈠崟30鍒嗛挓鍚庤繃鏈熷鐞�
- * <p>
- * 闆嗙兢娴嬭瘯閫氳繃 鍚屼竴涓暟鎹彧浼氳娑堣垂涓�娆� 鍋氬ソ浜嬪姟琛ュ伩
- * 闆嗙兢娴嬭瘯娴佺▼ 涓ゅ彴闆嗙兢鍒嗗埆寮�鍚闃� 鍦ㄥ叾涓竴鍙板彂閫佹暟鎹� 瑙傚療鎺ユ敹娑堟伅鐨勮寰�
- *
- * @author Lion Li
- * @version 3.6.0
- */
-@Slf4j
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/queue/delayed")
-public class DelayedQueueController {
-
-    /**
-     * 璁㈤槄闃熷垪
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    @GetMapping("/subscribe")
-    public R<Void> subscribe(String queueName) {
-        log.info("閫氶亾: {} 鐩戝惉涓�......", queueName);
-        // 椤圭洰鍒濆鍖栬缃竴娆″嵆鍙�
-        QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> {
-            // 瑙傚療鎺ユ敹鏃堕棿
-            log.info("閫氶亾: {}, 鏀跺埌鏁版嵁: {}", queueName, orderNum);
-        });
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 娣诲姞闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param orderNum  璁㈠崟鍙�
-     * @param time      寤惰繜鏃堕棿(绉�)
-     */
-    @GetMapping("/add")
-    public R<Void> add(String queueName, String orderNum, Long time) {
-        QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS);
-        // 瑙傚療鍙戦�佹椂闂�
-        log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}", queueName, orderNum);
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 鍒犻櫎闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param orderNum  璁㈠崟鍙�
-     */
-    @GetMapping("/remove")
-    public R<Void> remove(String queueName, String orderNum) {
-        if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) {
-            log.info("閫氶亾: {} , 鍒犻櫎鏁版嵁: {}", queueName, orderNum);
-        } else {
-            return R.fail("鎿嶄綔澶辫触");
-        }
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 閿�姣侀槦鍒�
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    @GetMapping("/destroy")
-    public R<Void> destroy(String queueName) {
-        // 鐢ㄥ畬浜嗕竴瀹氳閿�姣� 鍚﹀垯浼氫竴鐩村瓨鍦�
-        QueueUtils.destroyDelayedQueue(queueName);
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java
deleted file mode 100644
index 4a60232..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.ruoyi.demo.controller.queue;
-
-import cn.hutool.core.util.RandomUtil;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.redis.QueueUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 浼樺厛闃熷垪 婕旂ず妗堜緥
- * <p>
- * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
- * <p>
- * 闆嗙兢娴嬭瘯閫氳繃 鍚屼竴涓秷鎭彧浼氳娑堣垂涓�娆� 鍋氬ソ浜嬪姟琛ュ伩
- * 闆嗙兢娴嬭瘯娴佺▼ 鍦ㄥ叾涓竴鍙板彂閫佹暟鎹� 涓ょ鍒嗗埆璋冪敤鑾峰彇鎺ュ彛 涓�娆¤幏鍙栦竴鏉�
- *
- * @author Lion Li
- * @version 3.6.0
- */
-@Slf4j
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/queue/priority")
-public class PriorityQueueController {
-
-    /**
-     * 娣诲姞闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    @GetMapping("/add")
-    public R<Void> add(String queueName) {
-        // 鐢ㄥ畬浜嗕竴瀹氳閿�姣� 鍚﹀垯浼氫竴鐩村瓨鍦�
-        boolean b = QueueUtils.destroyQueue(queueName);
-        log.info("閫氶亾: {} , 鍒犻櫎: {}", queueName, b);
-
-        for (int i = 0; i < 10; i++) {
-            int randomNum = RandomUtil.randomInt(10);
-            PriorityDemo data = new PriorityDemo();
-            data.setName("data-" + i);
-            data.setOrderNum(randomNum);
-            if (QueueUtils.addPriorityQueueObject(queueName, data)) {
-                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}", queueName, data);
-            } else {
-                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}, 鍙戦�佸け璐�", queueName, data);
-            }
-        }
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 鍒犻櫎闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     * @param name      瀵硅薄鍚�
-     * @param orderNum  鎺掑簭鍙�
-     */
-    @GetMapping("/remove")
-    public R<Void> remove(String queueName, String name, Integer orderNum) {
-        PriorityDemo data = new PriorityDemo();
-        data.setName(name);
-        data.setOrderNum(orderNum);
-        if (QueueUtils.removeQueueObject(queueName, data)) {
-            log.info("閫氶亾: {} , 鍒犻櫎鏁版嵁: {}", queueName, data);
-        } else {
-            return R.fail("鎿嶄綔澶辫触");
-        }
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-    /**
-     * 鑾峰彇闃熷垪鏁版嵁
-     *
-     * @param queueName 闃熷垪鍚�
-     */
-    @GetMapping("/get")
-    public R<Void> get(String queueName) {
-        PriorityDemo data;
-        do {
-            data = QueueUtils.getQueueObject(queueName);
-            log.info("閫氶亾: {} , 鑾峰彇鏁版嵁: {}", queueName, data);
-        } while (data != null);
-        return R.ok("鎿嶄綔鎴愬姛");
-    }
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java
deleted file mode 100644
index 2484e39..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.ruoyi.demo.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serial;
-
-/**
- * 娴嬭瘯鍗曡〃瀵硅薄 test_demo
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("test_demo")
-public class TestDemo extends BaseEntity {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 涓婚敭
-     */
-    @TableId(value = "id")
-    private Long id;
-
-    /**
-     * 閮ㄩ棬id
-     */
-    private Long deptId;
-
-    /**
-     * 鐢ㄦ埛id
-     */
-    private Long userId;
-
-    /**
-     * 鎺掑簭鍙�
-     */
-    @OrderBy(asc = false, sort = 1)
-    private Integer orderNum;
-
-    /**
-     * key閿�
-     */
-    private String testKey;
-
-    /**
-     * 鍊�
-     */
-    private String value;
-
-    /**
-     * 鐗堟湰
-     */
-    @Version
-    private Long version;
-
-    /**
-     * 鍒犻櫎鏍囧織
-     */
-    @TableLogic
-    private Long delFlag;
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java
deleted file mode 100644
index 4a5ea94..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.ruoyi.demo.domain;
-
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.annotation.Version;
-import com.ruoyi.common.core.domain.TreeEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serial;
-
-/**
- * 娴嬭瘯鏍戣〃瀵硅薄 test_tree
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("test_tree")
-public class TestTree extends TreeEntity<TestTree> {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 涓婚敭
-     */
-    @TableId(value = "id")
-    private Long id;
-
-    /**
-     * 閮ㄩ棬id
-     */
-    private Long deptId;
-
-    /**
-     * 鐢ㄦ埛id
-     */
-    private Long userId;
-
-    /**
-     * 鏍戣妭鐐瑰悕
-     */
-    private String treeName;
-
-    /**
-     * 鐗堟湰
-     */
-    @Version
-    private Long version;
-
-    /**
-     * 鍒犻櫎鏍囧織
-     */
-    @TableLogic
-    private Long delFlag;
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java
deleted file mode 100644
index 18e0411..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.ruoyi.demo.domain.bo;
-
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-/**
- * 娴嬭瘯鍗曡〃涓氬姟瀵硅薄 test_demo
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class TestDemoBo extends BaseEntity {
-
-    /**
-     * 涓婚敭
-     */
-    @NotNull(message = "涓婚敭涓嶈兘涓虹┖", groups = {EditGroup.class})
-    private Long id;
-
-    /**
-     * 閮ㄩ棬id
-     */
-    @NotNull(message = "閮ㄩ棬id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    private Long deptId;
-
-    /**
-     * 鐢ㄦ埛id
-     */
-    @NotNull(message = "鐢ㄦ埛id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    private Long userId;
-
-    /**
-     * 鎺掑簭鍙�
-     */
-    @NotNull(message = "鎺掑簭鍙蜂笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
-    private Integer orderNum;
-
-    /**
-     * key閿�
-     */
-    @NotBlank(message = "key閿笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
-    private String testKey;
-
-    /**
-     * 鍊�
-     */
-    @NotBlank(message = "鍊间笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
-    private String value;
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java
deleted file mode 100644
index b93cc92..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.demo.domain.bo;
-
-import com.ruoyi.common.core.domain.TreeEntity;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-
-/**
- * 娴嬭瘯鏍戣〃涓氬姟瀵硅薄 test_tree
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class TestTreeBo extends TreeEntity<TestTreeBo> {
-
-    /**
-     * 涓婚敭
-     */
-    @NotNull(message = "涓婚敭涓嶈兘涓虹┖", groups = {EditGroup.class})
-    private Long id;
-
-    /**
-     * 閮ㄩ棬id
-     */
-    @NotNull(message = "閮ㄩ棬id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    private Long deptId;
-
-    /**
-     * 鐢ㄦ埛id
-     */
-    @NotNull(message = "鐢ㄦ埛id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    private Long userId;
-
-    /**
-     * 鏍戣妭鐐瑰悕
-     */
-    @NotBlank(message = "鏍戣妭鐐瑰悕涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    private String treeName;
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
deleted file mode 100644
index 11a3d50..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.ruoyi.demo.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.annotation.DataColumn;
-import com.ruoyi.common.annotation.DataPermission;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.demo.domain.TestDemo;
-import com.ruoyi.demo.domain.vo.TestDemoVo;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 娴嬭瘯鍗曡〃Mapper鎺ュ彛
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-public interface TestDemoMapper extends BaseMapperPlus<TestDemoMapper, TestDemo, TestDemoVo> {
-
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "dept_id"),
-        @DataColumn(key = "userName", value = "user_id")
-    })
-    Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper);
-
-    @Override
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "dept_id"),
-        @DataColumn(key = "userName", value = "user_id")
-    })
-    <P extends IPage<TestDemo>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
-
-    @Override
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "dept_id"),
-        @DataColumn(key = "userName", value = "user_id")
-    })
-    List<TestDemo> selectList(@Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
-
-    @Override
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "dept_id"),
-        @DataColumn(key = "userName", value = "user_id")
-    })
-    int updateById(@Param(Constants.ENTITY) TestDemo entity);
-
-    @Override
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "dept_id"),
-        @DataColumn(key = "userName", value = "user_id")
-    })
-    int deleteBatchIds(@Param(Constants.COLL) Collection<?> idList);
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
deleted file mode 100644
index e37a9a7..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ruoyi.demo.mapper;
-
-import com.ruoyi.common.annotation.DataColumn;
-import com.ruoyi.common.annotation.DataPermission;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.demo.domain.TestTree;
-import com.ruoyi.demo.domain.vo.TestTreeVo;
-
-/**
- * 娴嬭瘯鏍戣〃Mapper鎺ュ彛
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-@DataPermission({
-    @DataColumn(key = "deptName", value = "dept_id"),
-    @DataColumn(key = "userName", value = "user_id")
-})
-public interface TestTreeMapper extends BaseMapperPlus<TestTreeMapper, TestTree, TestTreeVo> {
-
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
deleted file mode 100644
index f6b82fd..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.ruoyi.demo.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.demo.domain.TestDemo;
-import com.ruoyi.demo.domain.bo.TestDemoBo;
-import com.ruoyi.demo.domain.vo.TestDemoVo;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 娴嬭瘯鍗曡〃Service鎺ュ彛
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-public interface ITestDemoService {
-
-    /**
-     * 鏌ヨ鍗曚釜
-     *
-     * @return
-     */
-    TestDemoVo queryById(Long id);
-
-    /**
-     * 鏌ヨ鍒楄〃
-     */
-    TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery);
-
-    /**
-     * 鑷畾涔夊垎椤垫煡璇�
-     */
-    TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery);
-
-    /**
-     * 鏌ヨ鍒楄〃
-     */
-    List<TestDemoVo> queryList(TestDemoBo bo);
-
-    /**
-     * 鏍规嵁鏂板涓氬姟瀵硅薄鎻掑叆娴嬭瘯鍗曡〃
-     *
-     * @param bo 娴嬭瘯鍗曡〃鏂板涓氬姟瀵硅薄
-     * @return
-     */
-    Boolean insertByBo(TestDemoBo bo);
-
-    /**
-     * 鏍规嵁缂栬緫涓氬姟瀵硅薄淇敼娴嬭瘯鍗曡〃
-     *
-     * @param bo 娴嬭瘯鍗曡〃缂栬緫涓氬姟瀵硅薄
-     * @return
-     */
-    Boolean updateByBo(TestDemoBo bo);
-
-    /**
-     * 鏍¢獙骞跺垹闄ゆ暟鎹�
-     *
-     * @param ids     涓婚敭闆嗗悎
-     * @param isValid 鏄惁鏍¢獙,true-鍒犻櫎鍓嶆牎楠�,false-涓嶆牎楠�
-     * @return
-     */
-    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
-
-    /**
-     * 鎵归噺淇濆瓨
-     */
-    Boolean saveBatch(List<TestDemo> list);
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java
deleted file mode 100644
index 7ed7cd5..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.ruoyi.demo.service.impl;
-
-import cn.hutool.core.bean.BeanUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.demo.domain.TestDemo;
-import com.ruoyi.demo.domain.bo.TestDemoBo;
-import com.ruoyi.demo.domain.vo.TestDemoVo;
-import com.ruoyi.demo.mapper.TestDemoMapper;
-import com.ruoyi.demo.service.ITestDemoService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 娴嬭瘯鍗曡〃Service涓氬姟灞傚鐞�
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-@RequiredArgsConstructor
-@Service
-public class TestDemoServiceImpl implements ITestDemoService {
-
-    private final TestDemoMapper baseMapper;
-
-    @Override
-    public TestDemoVo queryById(Long id) {
-        return baseMapper.selectVoById(id);
-    }
-
-    @Override
-    public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
-        Page<TestDemoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(result);
-    }
-
-    /**
-     * 鑷畾涔夊垎椤垫煡璇�
-     */
-    @Override
-    public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
-        Page<TestDemoVo> result = baseMapper.customPageList(pageQuery.build(), lqw);
-        return TableDataInfo.build(result);
-    }
-
-    @Override
-    public List<TestDemoVo> queryList(TestDemoBo bo) {
-        return baseMapper.selectVoList(buildQueryWrapper(bo));
-    }
-
-    private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) {
-        Map<String, Object> params = bo.getParams();
-        LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
-        lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
-        lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
-        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
-            TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
-        return lqw;
-    }
-
-    @Override
-    public Boolean insertByBo(TestDemoBo bo) {
-        TestDemo add = BeanUtil.toBean(bo, TestDemo.class);
-        validEntityBeforeSave(add);
-        boolean flag = baseMapper.insert(add) > 0;
-        if (flag) {
-            bo.setId(add.getId());
-        }
-        return flag;
-    }
-
-    @Override
-    public Boolean updateByBo(TestDemoBo bo) {
-        TestDemo update = BeanUtil.toBean(bo, TestDemo.class);
-        validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
-    }
-
-    /**
-     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
-     *
-     * @param entity 瀹炰綋绫绘暟鎹�
-     */
-    private void validEntityBeforeSave(TestDemo entity) {
-        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
-    }
-
-    @Override
-    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if (isValid) {
-            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
-        }
-        return baseMapper.deleteBatchIds(ids) > 0;
-    }
-
-    @Override
-    public Boolean saveBatch(List<TestDemo> list) {
-        return baseMapper.insertBatch(list);
-    }
-}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java
deleted file mode 100644
index 3e7fa20..0000000
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.ruoyi.demo.service.impl;
-
-import cn.hutool.core.bean.BeanUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.demo.domain.TestTree;
-import com.ruoyi.demo.domain.bo.TestTreeBo;
-import com.ruoyi.demo.domain.vo.TestTreeVo;
-import com.ruoyi.demo.mapper.TestTreeMapper;
-import com.ruoyi.demo.service.ITestTreeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 娴嬭瘯鏍戣〃Service涓氬姟灞傚鐞�
- *
- * @author Lion Li
- * @date 2021-07-26
- */
-// @DS("slave") // 鍒囨崲浠庡簱鏌ヨ
-@RequiredArgsConstructor
-@Service
-public class TestTreeServiceImpl implements ITestTreeService {
-
-    private final TestTreeMapper baseMapper;
-
-    @Override
-    public TestTreeVo queryById(Long id) {
-        return baseMapper.selectVoById(id);
-    }
-
-    // @DS("slave") // 鍒囨崲浠庡簱鏌ヨ
-    @Override
-    public List<TestTreeVo> queryList(TestTreeBo bo) {
-        LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo);
-        return baseMapper.selectVoList(lqw);
-    }
-
-    private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) {
-        Map<String, Object> params = bo.getParams();
-        LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
-        lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
-        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
-            TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
-        return lqw;
-    }
-
-    @Override
-    public Boolean insertByBo(TestTreeBo bo) {
-        TestTree add = BeanUtil.toBean(bo, TestTree.class);
-        validEntityBeforeSave(add);
-        boolean flag = baseMapper.insert(add) > 0;
-        if (flag) {
-            bo.setId(add.getId());
-        }
-        return flag;
-    }
-
-    @Override
-    public Boolean updateByBo(TestTreeBo bo) {
-        TestTree update = BeanUtil.toBean(bo, TestTree.class);
-        validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
-    }
-
-    /**
-     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
-     *
-     * @param entity 瀹炰綋绫绘暟鎹�
-     */
-    private void validEntityBeforeSave(TestTree entity) {
-        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
-    }
-
-    @Override
-    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if (isValid) {
-            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
-        }
-        return baseMapper.deleteBatchIds(ids) > 0;
-    }
-}
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
deleted file mode 100644
index 21b65b7..0000000
--- a/ruoyi-framework/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>
-        <artifactId>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-framework</artifactId>
-
-    <description>
-        framework妗嗘灦鏍稿績
-    </description>
-
-    <dependencies>
-
-        <!-- SpringBoot Web瀹瑰櫒 -->
-         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-             <exclusions>
-                 <exclusion>
-                     <artifactId>spring-boot-starter-tomcat</artifactId>
-                     <groupId>org.springframework.boot</groupId>
-                 </exclusion>
-             </exclusions>
-        </dependency>
-        <!-- web 瀹瑰櫒浣跨敤 undertow 鎬ц兘鏇村己 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-undertow</artifactId>
-        </dependency>
-
-        <!-- SpringBoot 鎷︽埅鍣� -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
-        </dependency>
-
-        <!-- sql鎬ц兘鍒嗘瀽鎻掍欢 -->
-        <dependency>
-            <groupId>p6spy</groupId>
-            <artifactId>p6spy</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-actuator</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>de.codecentric</groupId>
-            <artifactId>spring-boot-admin-starter-client</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>transmittable-thread-local</artifactId>
-        </dependency>
-
-        <!-- 绯荤粺妯″潡-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
deleted file mode 100644
index e7efb02..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package com.ruoyi.framework.aspectj;
-
-import cn.hutool.core.lang.Dict;
-import cn.hutool.core.map.MapUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.domain.event.OperLogEvent;
-import com.ruoyi.common.enums.BusinessStatus;
-import com.ruoyi.common.enums.HttpMethod;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.AfterReturning;
-import org.aspectj.lang.annotation.AfterThrowing;
-import org.aspectj.lang.annotation.Aspect;
-import org.springframework.stereotype.Component;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * 鎿嶄綔鏃ュ織璁板綍澶勭悊
- *
- * @author Lion Li
- */
-@Slf4j
-@Aspect
-@Component
-public class LogAspect {
-
-    /**
-     * 鎺掗櫎鏁忔劅灞炴�у瓧娈�
-     */
-    public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
-
-    /**
-     * 澶勭悊瀹岃姹傚悗鎵ц
-     *
-     * @param joinPoint 鍒囩偣
-     */
-    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
-    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
-        handleLog(joinPoint, controllerLog, null, jsonResult);
-    }
-
-    /**
-     * 鎷︽埅寮傚父鎿嶄綔
-     *
-     * @param joinPoint 鍒囩偣
-     * @param e         寮傚父
-     */
-    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
-    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
-        handleLog(joinPoint, controllerLog, e, null);
-    }
-
-    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
-        try {
-
-            // *========鏁版嵁搴撴棩蹇�=========*//
-            OperLogEvent operLog = new OperLogEvent();
-            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
-            // 璇锋眰鐨勫湴鍧�
-            String ip = ServletUtils.getClientIP();
-            operLog.setOperIp(ip);
-            operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
-            operLog.setOperName(LoginHelper.getUsername());
-
-            if (e != null) {
-                operLog.setStatus(BusinessStatus.FAIL.ordinal());
-                operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
-            }
-            // 璁剧疆鏂规硶鍚嶇О
-            String className = joinPoint.getTarget().getClass().getName();
-            String methodName = joinPoint.getSignature().getName();
-            operLog.setMethod(className + "." + methodName + "()");
-            // 璁剧疆璇锋眰鏂瑰紡
-            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
-            // 澶勭悊璁剧疆娉ㄨВ涓婄殑鍙傛暟
-            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
-            // 鍙戝竷浜嬩欢淇濆瓨鏁版嵁搴�
-            SpringUtils.context().publishEvent(operLog);
-        } catch (Exception exp) {
-            // 璁板綍鏈湴寮傚父鏃ュ織
-            log.error("寮傚父淇℃伅:{}", exp.getMessage());
-            exp.printStackTrace();
-        }
-    }
-
-    /**
-     * 鑾峰彇娉ㄨВ涓鏂规硶鐨勬弿杩颁俊鎭� 鐢ㄤ簬Controller灞傛敞瑙�
-     *
-     * @param log     鏃ュ織
-     * @param operLog 鎿嶄綔鏃ュ織
-     * @throws Exception
-     */
-    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception {
-        // 璁剧疆action鍔ㄤ綔
-        operLog.setBusinessType(log.businessType().ordinal());
-        // 璁剧疆鏍囬
-        operLog.setTitle(log.title());
-        // 璁剧疆鎿嶄綔浜虹被鍒�
-        operLog.setOperatorType(log.operatorType().ordinal());
-        // 鏄惁闇�瑕佷繚瀛榬equest锛屽弬鏁板拰鍊�
-        if (log.isSaveRequestData()) {
-            // 鑾峰彇鍙傛暟鐨勪俊鎭紝浼犲叆鍒版暟鎹簱涓��
-            setRequestValue(joinPoint, operLog);
-        }
-        // 鏄惁闇�瑕佷繚瀛榬esponse锛屽弬鏁板拰鍊�
-        if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) {
-            operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 2000));
-        }
-    }
-
-    /**
-     * 鑾峰彇璇锋眰鐨勫弬鏁帮紝鏀惧埌log涓�
-     *
-     * @param operLog 鎿嶄綔鏃ュ織
-     * @throws Exception 寮傚父
-     */
-    private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception {
-        String requestMethod = operLog.getRequestMethod();
-        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
-            String params = argsArrayToString(joinPoint.getArgs());
-            operLog.setOperParam(StringUtils.substring(params, 0, 2000));
-        } else {
-            Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
-            MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES);
-            operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000));
-        }
-    }
-
-    /**
-     * 鍙傛暟鎷艰
-     */
-    private String argsArrayToString(Object[] paramsArray) {
-        StringBuilder params = new StringBuilder();
-        if (paramsArray != null && paramsArray.length > 0) {
-            for (Object o : paramsArray) {
-                if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {
-                    try {
-                        String str = JsonUtils.toJsonString(o);
-                        Dict dict = JsonUtils.parseMap(str);
-                        if (MapUtil.isNotEmpty(dict)) {
-                            MapUtil.removeAny(dict, EXCLUDE_PROPERTIES);
-                            str = JsonUtils.toJsonString(dict);
-                        }
-                        params.append(str).append(" ");
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                }
-            }
-        }
-        return params.toString().trim();
-    }
-
-    /**
-     * 鍒ゆ柇鏄惁闇�瑕佽繃婊ょ殑瀵硅薄銆�
-     *
-     * @param o 瀵硅薄淇℃伅銆�
-     * @return 濡傛灉鏄渶瑕佽繃婊ょ殑瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆�
-     */
-    @SuppressWarnings("rawtypes")
-    public boolean isFilterObject(final Object o) {
-        Class<?> clazz = o.getClass();
-        if (clazz.isArray()) {
-            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
-        } else if (Collection.class.isAssignableFrom(clazz)) {
-            Collection collection = (Collection) o;
-            for (Object value : collection) {
-                return value instanceof MultipartFile;
-            }
-        } else if (Map.class.isAssignableFrom(clazz)) {
-            Map map = (Map) o;
-            for (Object value : map.entrySet()) {
-                Map.Entry entry = (Map.Entry) value;
-                return entry.getValue() instanceof MultipartFile;
-            }
-        }
-        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
-            || o instanceof BindingResult;
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
deleted file mode 100644
index 542b16b..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.ruoyi.framework.aspectj;
-
-import com.ruoyi.common.annotation.RateLimiter;
-import com.ruoyi.common.enums.LimitType;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.redisson.api.RateType;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-
-/**
- * 闄愭祦澶勭悊
- *
- * @author Lion Li
- */
-@Slf4j
-@Aspect
-@Component
-public class RateLimiterAspect {
-
-    @Before("@annotation(rateLimiter)")
-    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
-        int time = rateLimiter.time();
-        int count = rateLimiter.count();
-        String combineKey = getCombineKey(rateLimiter, point);
-        try {
-            RateType rateType = RateType.OVERALL;
-            if (rateLimiter.limitType() == LimitType.CLUSTER) {
-                rateType = RateType.PER_CLIENT;
-            }
-            long number = RedisUtils.rateLimiter(combineKey, rateType, count, time);
-            if (number == -1) {
-                throw new ServiceException(MessageUtils.message("rate.limiter.message"));
-            }
-            log.info("闄愬埗浠ょ墝 => {}, 鍓╀綑浠ょ墝 => {}, 缂撳瓨key => '{}'", count, number, combineKey);
-        } catch (ServiceException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new RuntimeException("鏈嶅姟鍣ㄩ檺娴佸紓甯革紝璇风◢鍊欏啀璇�");
-        }
-    }
-
-    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
-        StringBuilder stringBuffer = new StringBuilder(rateLimiter.key());
-        if (rateLimiter.limitType() == LimitType.IP) {
-            // 鑾峰彇璇锋眰ip
-            stringBuffer.append(ServletUtils.getClientIP()).append("-");
-        } else if (rateLimiter.limitType() == LimitType.CLUSTER) {
-            // 鑾峰彇瀹㈡埛绔疄渚媔d
-            stringBuffer.append(RedisUtils.getClient().getId()).append("-");
-        }
-        MethodSignature signature = (MethodSignature) point.getSignature();
-        Method method = signature.getMethod();
-        Class<?> targetClass = method.getDeclaringClass();
-        stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
-        return stringBuffer.toString();
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java
deleted file mode 100644
index 2972a9f..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.ruoyi.framework.aspectj;
-
-import cn.dev33.satoken.SaManager;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.crypto.SecureUtil;
-import com.ruoyi.common.annotation.RepeatSubmit;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.AfterReturning;
-import org.aspectj.lang.annotation.AfterThrowing;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.springframework.stereotype.Component;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.time.Duration;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * 闃叉閲嶅鎻愪氦(鍙傝�冪編鍥TIS闃查噸绯荤粺)
- *
- * @author Lion Li
- */
-@Slf4j
-@RequiredArgsConstructor
-@Aspect
-@Component
-public class RepeatSubmitAspect {
-
-    private static final ThreadLocal<String> KEY_CACHE = new ThreadLocal<>();
-
-    @Before("@annotation(repeatSubmit)")
-    public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable {
-        // 濡傛灉娉ㄨВ涓嶄负0 鍒欎娇鐢ㄦ敞瑙f暟鍊�
-        long interval = 0;
-        if (repeatSubmit.interval() > 0) {
-            interval = repeatSubmit.timeUnit().toMillis(repeatSubmit.interval());
-        }
-        if (interval < 1000) {
-            throw new ServiceException("閲嶅鎻愪氦闂撮殧鏃堕棿涓嶈兘灏忎簬'1'绉�");
-        }
-        HttpServletRequest request = ServletUtils.getRequest();
-        String nowParams = argsArrayToString(point.getArgs());
-
-        // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
-        String url = request.getRequestURI();
-
-        // 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
-        String submitKey = StringUtils.trimToEmpty(request.getHeader(SaManager.getConfig().getTokenName()));
-
-        submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
-        // 鍞竴鏍囪瘑锛堟寚瀹歬ey + url + 娑堟伅澶达級
-        String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
-        String key = RedisUtils.getCacheObject(cacheRepeatKey);
-        if (key == null) {
-            RedisUtils.setCacheObject(cacheRepeatKey, "", Duration.ofMillis(interval));
-            KEY_CACHE.set(cacheRepeatKey);
-        } else {
-            String message = repeatSubmit.message();
-            if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) {
-                message = MessageUtils.message(StringUtils.substring(message, 1, message.length() - 1));
-            }
-            throw new ServiceException(message);
-        }
-    }
-
-    /**
-     * 澶勭悊瀹岃姹傚悗鎵ц
-     *
-     * @param joinPoint 鍒囩偣
-     */
-    @AfterReturning(pointcut = "@annotation(repeatSubmit)", returning = "jsonResult")
-    public void doAfterReturning(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Object jsonResult) {
-        if (jsonResult instanceof R) {
-            try {
-                R<?> r = (R<?>) jsonResult;
-                // 鎴愬姛鍒欎笉鍒犻櫎redis鏁版嵁 淇濊瘉鍦ㄦ湁鏁堟椂闂村唴鏃犳硶閲嶅鎻愪氦
-                if (r.getCode() == R.SUCCESS) {
-                    return;
-                }
-                RedisUtils.deleteObject(KEY_CACHE.get());
-            } finally {
-                KEY_CACHE.remove();
-            }
-        }
-    }
-
-    /**
-     * 鎷︽埅寮傚父鎿嶄綔
-     *
-     * @param joinPoint 鍒囩偣
-     * @param e         寮傚父
-     */
-    @AfterThrowing(value = "@annotation(repeatSubmit)", throwing = "e")
-    public void doAfterThrowing(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Exception e) {
-        RedisUtils.deleteObject(KEY_CACHE.get());
-        KEY_CACHE.remove();
-    }
-
-    /**
-     * 鍙傛暟鎷艰
-     */
-    private String argsArrayToString(Object[] paramsArray) {
-        StringBuilder params = new StringBuilder();
-        if (paramsArray != null && paramsArray.length > 0) {
-            for (Object o : paramsArray) {
-                if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) {
-                    try {
-                        params.append(JsonUtils.toJsonString(o)).append(" ");
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                }
-            }
-        }
-        return params.toString().trim();
-    }
-
-    /**
-     * 鍒ゆ柇鏄惁闇�瑕佽繃婊ょ殑瀵硅薄銆�
-     *
-     * @param o 瀵硅薄淇℃伅銆�
-     * @return 濡傛灉鏄渶瑕佽繃婊ょ殑瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆�
-     */
-    @SuppressWarnings("rawtypes")
-    public boolean isFilterObject(final Object o) {
-        Class<?> clazz = o.getClass();
-        if (clazz.isArray()) {
-            return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
-        } else if (Collection.class.isAssignableFrom(clazz)) {
-            Collection collection = (Collection) o;
-            for (Object value : collection) {
-                return value instanceof MultipartFile;
-            }
-        } else if (Map.class.isAssignableFrom(clazz)) {
-            Map map = (Map) o;
-            for (Object value : map.entrySet()) {
-                Map.Entry entry = (Map.Entry) value;
-                return entry.getValue() instanceof MultipartFile;
-            }
-        }
-        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
-            || o instanceof BindingResult;
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java
deleted file mode 100644
index 072eef9..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.ruoyi.framework.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.EnableAspectJAutoProxy;
-
-/**
- * 绋嬪簭娉ㄨВ閰嶇疆
- *
- * @author Lion Li
- */
-@Configuration
-// 琛ㄧず閫氳繃aop妗嗘灦鏆撮湶璇ヤ唬鐞嗗璞�,AopContext鑳藉璁块棶
-@EnableAspectJAutoProxy(exposeProxy = true)
-public class ApplicationConfig {
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java
deleted file mode 100644
index e752743..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/AsyncConfig.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.core.util.ArrayUtil;
-import com.ruoyi.common.exception.ServiceException;
-import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.AsyncConfigurer;
-import org.springframework.scheduling.annotation.EnableAsync;
-
-import java.util.Arrays;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * 寮傛閰嶇疆
- *
- * @author Lion Li
- */
-@EnableAsync(proxyTargetClass = true)
-@Configuration
-public class AsyncConfig implements AsyncConfigurer {
-
-    @Autowired
-    @Qualifier("scheduledExecutorService")
-    private ScheduledExecutorService scheduledExecutorService;
-
-    /**
-     * 鑷畾涔� @Async 娉ㄨВ浣跨敤绯荤粺绾跨▼姹�
-     */
-    @Override
-    public Executor getAsyncExecutor() {
-        return scheduledExecutorService;
-    }
-
-    /**
-     * 寮傛鎵ц寮傚父澶勭悊
-     */
-    @Override
-    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
-        return (throwable, method, objects) -> {
-            throwable.printStackTrace();
-            StringBuilder sb = new StringBuilder();
-            sb.append("Exception message - ").append(throwable.getMessage())
-                .append(", Method name - ").append(method.getName());
-            if (ArrayUtil.isNotEmpty(objects)) {
-                sb.append(", Parameter value - ").append(Arrays.toString(objects));
-            }
-            throw new ServiceException(sb.toString());
-        };
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
deleted file mode 100644
index b284216..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.captcha.CaptchaUtil;
-import cn.hutool.captcha.CircleCaptcha;
-import cn.hutool.captcha.LineCaptcha;
-import cn.hutool.captcha.ShearCaptcha;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-
-import java.awt.*;
-
-/**
- * 楠岃瘉鐮侀厤缃�
- *
- * @author Lion Li
- */
-@Configuration
-public class CaptchaConfig {
-
-    private static final int WIDTH = 160;
-    private static final int HEIGHT = 60;
-    private static final Color BACKGROUND = Color.PINK;
-    private static final Font FONT = new Font("Arial", Font.BOLD, 48);
-
-    /**
-     * 鍦嗗湀骞叉壈楠岃瘉鐮�
-     */
-    @Lazy
-    @Bean
-    public CircleCaptcha circleCaptcha() {
-        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(WIDTH, HEIGHT);
-        captcha.setBackground(BACKGROUND);
-        captcha.setFont(FONT);
-        return captcha;
-    }
-
-    /**
-     * 绾挎骞叉壈鐨勯獙璇佺爜
-     */
-    @Lazy
-    @Bean
-    public LineCaptcha lineCaptcha() {
-        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(WIDTH, HEIGHT);
-        captcha.setBackground(BACKGROUND);
-        captcha.setFont(FONT);
-        return captcha;
-    }
-
-    /**
-     * 鎵洸骞叉壈楠岃瘉鐮�
-     */
-    @Lazy
-    @Bean
-    public ShearCaptcha shearCaptcha() {
-        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(WIDTH, HEIGHT);
-        captcha.setBackground(BACKGROUND);
-        captcha.setFont(FONT);
-        return captcha;
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java
deleted file mode 100644
index 7177d14..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.ruoyi.common.filter.RepeatableFilter;
-import com.ruoyi.common.filter.XssFilter;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.config.properties.XssProperties;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import jakarta.servlet.DispatcherType;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Filter閰嶇疆
- *
- * @author Lion Li
- */
-@Configuration
-public class FilterConfig {
-
-    @Autowired
-    private XssProperties xssProperties;
-
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    @Bean
-    @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
-    public FilterRegistrationBean xssFilterRegistration() {
-        FilterRegistrationBean registration = new FilterRegistrationBean();
-        registration.setDispatcherTypes(DispatcherType.REQUEST);
-        registration.setFilter(new XssFilter());
-        registration.addUrlPatterns(StringUtils.split(xssProperties.getUrlPatterns(), ","));
-        registration.setName("xssFilter");
-        registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
-        Map<String, String> initParameters = new HashMap<String, String>();
-        initParameters.put("excludes", xssProperties.getExcludes());
-        registration.setInitParameters(initParameters);
-        return registration;
-    }
-
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    @Bean
-    public FilterRegistrationBean someFilterRegistration() {
-        FilterRegistrationBean registration = new FilterRegistrationBean();
-        registration.setFilter(new RepeatableFilter());
-        registration.addUrlPatterns("/*");
-        registration.setName("repeatableFilter");
-        registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
-        return registration;
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
deleted file mode 100644
index f664f03..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.core.util.StrUtil;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.LocaleResolver;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.Locale;
-
-/**
- * 鍥介檯鍖栭厤缃�
- *
- * @author Lion Li
- */
-@Configuration
-public class I18nConfig {
-
-    @Bean
-    public LocaleResolver localeResolver() {
-        return new I18nLocaleResolver();
-    }
-
-    /**
-     * 鑾峰彇璇锋眰澶村浗闄呭寲淇℃伅
-     */
-    static class I18nLocaleResolver implements LocaleResolver {
-
-        @Override
-        public Locale resolveLocale(HttpServletRequest httpServletRequest) {
-            String language = httpServletRequest.getHeader("content-language");
-            Locale locale = Locale.getDefault();
-            if (StrUtil.isNotBlank(language)) {
-                String[] split = language.split("_");
-                locale = new Locale(split[0], split[1]);
-            }
-            return locale;
-        }
-
-        @Override
-        public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
-
-        }
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonConfig.java
deleted file mode 100644
index eace537..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonConfig.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
-import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
-import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
-import com.ruoyi.framework.jackson.BigNumberSerializer;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.TimeZone;
-
-/**
- * jackson 閰嶇疆
- *
- * @author Lion Li
- */
-@Slf4j
-@Configuration
-public class JacksonConfig {
-
-    @Bean
-    public Jackson2ObjectMapperBuilderCustomizer customizer() {
-        return builder -> {
-            // 鍏ㄥ眬閰嶇疆搴忓垪鍖栬繑鍥� JSON 澶勭悊
-            JavaTimeModule javaTimeModule = new JavaTimeModule();
-            javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
-            javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
-            javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
-            javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
-            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
-            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
-            builder.modules(javaTimeModule);
-            builder.timeZone(TimeZone.getDefault());
-            log.info("鍒濆鍖� jackson 閰嶇疆");
-        };
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java
deleted file mode 100644
index 20769aa..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MailConfig.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.extra.mail.MailAccount;
-import com.ruoyi.framework.config.properties.MailProperties;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * JavaMail 閰嶇疆
- *
- * @author Michelle.Chung
- */
-@Configuration
-public class MailConfig {
-
-    @Bean
-    @ConditionalOnProperty(value = "mail.enabled", havingValue = "true")
-    public MailAccount mailAccount(MailProperties mailProperties) {
-        MailAccount account = new MailAccount();
-        account.setHost(mailProperties.getHost());
-        account.setPort(mailProperties.getPort());
-        account.setAuth(mailProperties.getAuth());
-        account.setFrom(mailProperties.getFrom());
-        account.setUser(mailProperties.getUser());
-        account.setPass(mailProperties.getPass());
-        account.setSocketFactoryPort(mailProperties.getPort());
-        account.setStarttlsEnable(mailProperties.getStarttlsEnable());
-        account.setSslEnable(mailProperties.getSslEnable());
-        account.setTimeout(mailProperties.getTimeout());
-        account.setConnectionTimeout(mailProperties.getConnectionTimeout());
-        return account;
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
deleted file mode 100644
index ffd2c15..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.core.net.NetUtil;
-import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
-import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
-import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
-import com.ruoyi.framework.handler.CreateAndUpdateMetaObjectHandler;
-import com.ruoyi.framework.interceptor.PlusDataPermissionInterceptor;
-import org.mybatis.spring.annotation.MapperScan;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-/**
- * mybatis-plus閰嶇疆绫�(涓嬫柟娉ㄩ噴鏈夋彃浠朵粙缁�)
- *
- * @author Lion Li
- */
-@EnableTransactionManagement(proxyTargetClass = true)
-@Configuration
-@MapperScan("${mybatis-plus.mapperPackage}")
-public class MybatisPlusConfig {
-
-    @Bean
-    public MybatisPlusInterceptor mybatisPlusInterceptor() {
-        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
-        // 鏁版嵁鏉冮檺澶勭悊
-        interceptor.addInnerInterceptor(dataPermissionInterceptor());
-        // 鍒嗛〉鎻掍欢
-        interceptor.addInnerInterceptor(paginationInnerInterceptor());
-        // 涔愯閿佹彃浠�
-        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
-        return interceptor;
-    }
-
-    /**
-     * 鏁版嵁鏉冮檺鎷︽埅鍣�
-     */
-    public PlusDataPermissionInterceptor dataPermissionInterceptor() {
-        return new PlusDataPermissionInterceptor();
-    }
-
-    /**
-     * 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷
-     */
-    public PaginationInnerInterceptor paginationInnerInterceptor() {
-        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
-        // 璁剧疆鏈�澶у崟椤甸檺鍒舵暟閲忥紝榛樿 500 鏉★紝-1 涓嶅彈闄愬埗
-        paginationInnerInterceptor.setMaxLimit(-1L);
-        // 鍒嗛〉鍚堢悊鍖�
-        paginationInnerInterceptor.setOverflow(true);
-        return paginationInnerInterceptor;
-    }
-
-    /**
-     * 涔愯閿佹彃浠�
-     */
-    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
-        return new OptimisticLockerInnerInterceptor();
-    }
-
-    /**
-     * 鍏冨璞″瓧娈靛~鍏呮帶鍒跺櫒
-     */
-    @Bean
-    public MetaObjectHandler metaObjectHandler() {
-        return new CreateAndUpdateMetaObjectHandler();
-    }
-
-    /**
-     * 浣跨敤缃戝崱淇℃伅缁戝畾闆姳鐢熸垚鍣�
-     * 闃叉闆嗙兢闆姳ID閲嶅
-     */
-    @Bean
-    public IdentifierGenerator idGenerator() {
-        return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
-    }
-
-    /**
-     * PaginationInnerInterceptor 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷
-     * https://baomidou.com/pages/97710a/
-     * OptimisticLockerInnerInterceptor 涔愯閿佹彃浠�
-     * https://baomidou.com/pages/0d93c0/
-     * MetaObjectHandler 鍏冨璞″瓧娈靛~鍏呮帶鍒跺櫒
-     * https://baomidou.com/pages/4c6bcf/
-     * ISqlInjector sql娉ㄥ叆鍣�
-     * https://baomidou.com/pages/42ea4a/
-     * BlockAttackInnerInterceptor 濡傛灉鏄鍏ㄨ〃鐨勫垹闄ゆ垨鏇存柊鎿嶄綔锛屽氨浼氱粓姝㈣鎿嶄綔
-     * https://baomidou.com/pages/f9a237/
-     * IllegalSQLInnerInterceptor sql鎬ц兘瑙勮寖鎻掍欢(鍨冨溇SQL鎷︽埅)
-     * IdentifierGenerator 鑷畾涔変富閿瓥鐣�
-     * https://baomidou.com/pages/568eb2/
-     * TenantLineInnerInterceptor 澶氱鎴锋彃浠�
-     * https://baomidou.com/pages/aef2f2/
-     * DynamicTableNameInnerInterceptor 鍔ㄦ�佽〃鍚嶆彃浠�
-     * https://baomidou.com/pages/2a45ff/
-     */
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
deleted file mode 100644
index 8016ab8..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.ruoyi.framework.config.properties.RedissonProperties;
-import com.ruoyi.framework.handler.KeyPrefixHandler;
-import com.ruoyi.framework.manager.PlusSpringCacheManager;
-import lombok.extern.slf4j.Slf4j;
-import org.redisson.codec.JsonJacksonCodec;
-import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.cache.CacheManager;
-import org.springframework.cache.annotation.EnableCaching;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * redis閰嶇疆
- *
- * @author Lion Li
- */
-@Slf4j
-@Configuration
-@EnableCaching
-@EnableConfigurationProperties(RedissonProperties.class)
-public class RedisConfig {
-
-    @Autowired
-    private RedissonProperties redissonProperties;
-
-    @Autowired
-    private ObjectMapper objectMapper;
-
-    @Bean
-    public RedissonAutoConfigurationCustomizer redissonCustomizer() {
-        return config -> {
-            config.setThreads(redissonProperties.getThreads())
-                .setNettyThreads(redissonProperties.getNettyThreads())
-                .setCodec(new JsonJacksonCodec(objectMapper));
-            RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
-            if (ObjectUtil.isNotNull(singleServerConfig)) {
-                // 浣跨敤鍗曟満妯″紡
-                config.useSingleServer()
-                    //璁剧疆redis key鍓嶇紑
-                    .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
-                    .setTimeout(singleServerConfig.getTimeout())
-                    .setClientName(singleServerConfig.getClientName())
-                    .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
-                    .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
-                    .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
-                    .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize());
-            }
-            // 闆嗙兢閰嶇疆鏂瑰紡 鍙傝�冧笅鏂规敞閲�
-            RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
-            if (ObjectUtil.isNotNull(clusterServersConfig)) {
-                config.useClusterServers()
-                    //璁剧疆redis key鍓嶇紑
-                    .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix()))
-                    .setTimeout(clusterServersConfig.getTimeout())
-                    .setClientName(clusterServersConfig.getClientName())
-                    .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
-                    .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
-                    .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
-                    .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
-                    .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
-                    .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
-                    .setReadMode(clusterServersConfig.getReadMode())
-                    .setSubscriptionMode(clusterServersConfig.getSubscriptionMode());
-            }
-            log.info("鍒濆鍖� redis 閰嶇疆");
-        };
-    }
-
-    /**
-     * 鑷畾涔夌紦瀛樼鐞嗗櫒 鏁村悎spring-cache
-     */
-    @Bean
-    public CacheManager cacheManager() {
-        return new PlusSpringCacheManager();
-    }
-
-    /**
-     * redis闆嗙兢閰嶇疆 yml
-     *
-     * --- # redis 闆嗙兢閰嶇疆(鍗曟満涓庨泦缇ゅ彧鑳藉紑鍚竴涓彟涓�涓渶瑕佹敞閲婃帀)
-     * spring:
-     *   redis:
-     *     cluster:
-     *       nodes:
-     *         - 192.168.0.100:6379
-     *         - 192.168.0.101:6379
-     *         - 192.168.0.102:6379
-     *     # 瀵嗙爜
-     *     password:
-     *     # 杩炴帴瓒呮椂鏃堕棿
-     *     timeout: 10s
-     *     # 鏄惁寮�鍚痵sl
-     *     ssl: false
-     *
-     * redisson:
-     *   # 绾跨▼姹犳暟閲�
-     *   threads: 16
-     *   # Netty绾跨▼姹犳暟閲�
-     *   nettyThreads: 32
-     *   # 闆嗙兢閰嶇疆
-     *   clusterServersConfig:
-     *     # 瀹㈡埛绔悕绉�
-     *     clientName: ${ruoyi.name}
-     *     # master鏈�灏忕┖闂茶繛鎺ユ暟
-     *     masterConnectionMinimumIdleSize: 32
-     *     # master杩炴帴姹犲ぇ灏�
-     *     masterConnectionPoolSize: 64
-     *     # slave鏈�灏忕┖闂茶繛鎺ユ暟
-     *     slaveConnectionMinimumIdleSize: 32
-     *     # slave杩炴帴姹犲ぇ灏�
-     *     slaveConnectionPoolSize: 64
-     *     # 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
-     *     idleConnectionTimeout: 10000
-     *     # 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
-     *     timeout: 3000
-     *     # 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
-     *     subscriptionConnectionPoolSize: 50
-     *     # 璇诲彇妯″紡
-     *     readMode: "SLAVE"
-     *     # 璁㈤槄妯″紡
-     *     subscriptionMode: "MASTER"
-     */
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
deleted file mode 100644
index ea83338..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-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.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-/**
- * 閫氱敤閰嶇疆
- *
- * @author Lion Li
- */
-@Configuration
-public class ResourcesConfig implements WebMvcConfigurer {
-
-    @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-        // 鍏ㄥ眬璁块棶鎬ц兘鎷︽埅
-        registry.addInterceptor(new PlusWebInvokeTimeInterceptor());
-    }
-
-    @Override
-    public void addResourceHandlers(ResourceHandlerRegistry registry) {
-    }
-
-    /**
-     * 璺ㄥ煙閰嶇疆
-     */
-    @Bean
-    public CorsFilter corsFilter() {
-        CorsConfiguration config = new CorsConfiguration();
-        config.setAllowCredentials(true);
-        // 璁剧疆璁块棶婧愬湴鍧�
-        config.addAllowedOriginPattern("*");
-        // 璁剧疆璁块棶婧愯姹傚ご
-        config.addAllowedHeader("*");
-        // 璁剧疆璁块棶婧愯姹傛柟娉�
-        config.addAllowedMethod("*");
-        // 鏈夋晥鏈� 1800绉�
-        config.setMaxAge(1800L);
-        // 娣诲姞鏄犲皠璺緞锛屾嫤鎴竴鍒囪姹�
-        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-        source.registerCorsConfiguration("/**", config);
-        // 杩斿洖鏂扮殑CorsFilter
-        return new CorsFilter(source);
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java
deleted file mode 100644
index 2912286..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ruoyi.framework.config;
-
-import cn.dev33.satoken.interceptor.SaInterceptor;
-import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
-import cn.dev33.satoken.router.SaRouter;
-import cn.dev33.satoken.stp.StpLogic;
-import cn.dev33.satoken.stp.StpUtil;
-import com.ruoyi.framework.config.properties.SecurityProperties;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-/**
- * sa-token 閰嶇疆
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Slf4j
-@Configuration
-public class SaTokenConfig implements WebMvcConfigurer {
-
-    private final SecurityProperties securityProperties;
-
-    /**
-     * 娉ㄥ唽sa-token鐨勬嫤鎴櫒
-     */
-    @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-        // 娉ㄥ唽璺敱鎷︽埅鍣紝鑷畾涔夐獙璇佽鍒�
-        registry.addInterceptor(new SaInterceptor(handler -> {
-            // 鐧诲綍楠岃瘉 -- 鎺掗櫎澶氫釜璺緞
-            SaRouter
-                // 鑾峰彇鎵�鏈夌殑
-                .match("/**")
-                // 瀵规湭鎺掗櫎鐨勮矾寰勮繘琛屾鏌�
-                .check(() -> {
-                    // 妫�鏌ユ槸鍚︾櫥褰� 鏄惁鏈塼oken
-                    StpUtil.checkLogin();
-
-                    // 鏈夋晥鐜囧奖鍝� 鐢ㄤ簬涓存椂娴嬭瘯
-                    // if (log.isDebugEnabled()) {
-                    //     log.debug("鍓╀綑鏈夋晥鏃堕棿: {}", StpUtil.getTokenTimeout());
-                    //     log.debug("涓存椂鏈夋晥鏃堕棿: {}", StpUtil.getTokenActivityTimeout());
-                    // }
-
-                });
-        })).addPathPatterns("/**")
-            // 鎺掗櫎涓嶉渶瑕佹嫤鎴殑璺緞
-            .excludePathPatterns(securityProperties.getExcludes());
-    }
-
-    @Bean
-    public StpLogic getStpLogicJwt() {
-        // Sa-Token 鏁村悎 jwt (绠�鍗曟ā寮�)
-        return new StpLogicJwtForSimple();
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
deleted file mode 100644
index a84b731..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.config.properties.SwaggerProperties;
-import com.ruoyi.framework.handler.OpenApiHandler;
-import io.swagger.v3.oas.models.OpenAPI;
-import io.swagger.v3.oas.models.Paths;
-import io.swagger.v3.oas.models.info.Info;
-import io.swagger.v3.oas.models.security.SecurityRequirement;
-import lombok.RequiredArgsConstructor;
-import org.springdoc.core.configuration.SpringDocConfiguration;
-import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
-import org.springdoc.core.customizers.OpenApiCustomizer;
-import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
-import org.springdoc.core.properties.SpringDocConfigProperties;
-import org.springdoc.core.providers.JavadocProvider;
-import org.springdoc.core.service.OpenAPIService;
-import org.springdoc.core.service.SecurityService;
-import org.springdoc.core.utils.PropertyResolverUtils;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.web.ServerProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Swagger 鏂囨。閰嶇疆
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Configuration
-@AutoConfigureBefore(SpringDocConfiguration.class)
-@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true", matchIfMissing = true)
-public class SwaggerConfig {
-
-    private final SwaggerProperties swaggerProperties;
-    private final ServerProperties serverProperties;
-
-    @Bean
-    @ConditionalOnMissingBean(OpenAPI.class)
-    public OpenAPI openApi() {
-        OpenAPI openApi = new OpenAPI();
-        // 鏂囨。鍩烘湰淇℃伅
-        SwaggerProperties.InfoProperties infoProperties = swaggerProperties.getInfo();
-        Info info = convertInfo(infoProperties);
-        openApi.info(info);
-        // 鎵╁睍鏂囨。淇℃伅
-        openApi.externalDocs(swaggerProperties.getExternalDocs());
-        openApi.tags(swaggerProperties.getTags());
-        openApi.paths(swaggerProperties.getPaths());
-        openApi.components(swaggerProperties.getComponents());
-        Set<String> keySet = swaggerProperties.getComponents().getSecuritySchemes().keySet();
-        List<SecurityRequirement> list = new ArrayList<>();
-        SecurityRequirement securityRequirement = new SecurityRequirement();
-        keySet.forEach(securityRequirement::addList);
-        list.add(securityRequirement);
-        openApi.security(list);
-
-        return openApi;
-    }
-
-    private Info convertInfo(SwaggerProperties.InfoProperties infoProperties) {
-        Info info = new Info();
-        info.setTitle(infoProperties.getTitle());
-        info.setDescription(infoProperties.getDescription());
-        info.setContact(infoProperties.getContact());
-        info.setLicense(infoProperties.getLicense());
-        info.setVersion(infoProperties.getVersion());
-        return info;
-    }
-
-    /**
-     * 鑷畾涔� openapi 澶勭悊鍣�
-     */
-    @Bean
-    public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
-                                         SecurityService securityParser,
-                                         SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
-                                         Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers,
-                                         Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider) {
-        return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider);
-    }
-
-    /**
-     * 瀵瑰凡缁忕敓鎴愬ソ鐨� OpenApi 杩涜鑷畾涔夋搷浣�
-     */
-    @Bean
-    public OpenApiCustomizer openApiCustomiser() {
-        String contextPath = serverProperties.getServlet().getContextPath();
-        String finalContextPath;
-        if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) {
-            finalContextPath = "";
-        } else {
-            finalContextPath = contextPath;
-        }
-        // 瀵规墍鏈夎矾寰勫鍔犲墠缃笂涓嬫枃璺緞
-        return openApi -> {
-            Paths oldPaths = openApi.getPaths();
-            if (oldPaths instanceof PlusPaths) {
-                return;
-            }
-            PlusPaths newPaths = new PlusPaths();
-            oldPaths.forEach((k,v) -> newPaths.addPathItem(finalContextPath + k, v));
-            openApi.setPaths(newPaths);
-        };
-    }
-
-    /**
-     * 鍗曠嫭浣跨敤涓�涓被渚夸簬鍒ゆ柇 瑙e喅springdoc璺緞鎷兼帴閲嶅闂
-     *
-     * @author Lion Li
-     */
-    static class PlusPaths extends Paths {
-
-        public PlusPaths() {
-            super();
-        }
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java
deleted file mode 100644
index a85ad1e..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.ruoyi.framework.config;
-
-import com.ruoyi.common.utils.Threads;
-import com.ruoyi.framework.config.properties.ThreadPoolProperties;
-import org.apache.commons.lang3.concurrent.BasicThreadFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadPoolExecutor;
-
-/**
- * 绾跨▼姹犻厤缃�
- *
- * @author Lion Li
- **/
-@Configuration
-public class ThreadPoolConfig {
-
-    /**
-     * 鏍稿績绾跨▼鏁� = cpu 鏍稿績鏁� + 1
-     */
-    private final int core = Runtime.getRuntime().availableProcessors() + 1;
-
-    @Autowired
-    private ThreadPoolProperties threadPoolProperties;
-
-    @Bean(name = "threadPoolTaskExecutor")
-    @ConditionalOnProperty(prefix = "thread-pool", name = "enabled", havingValue = "true")
-    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
-        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
-        executor.setCorePoolSize(core);
-        executor.setMaxPoolSize(core * 2);
-        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
-        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
-        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
-        return executor;
-    }
-
-    /**
-     * 鎵ц鍛ㄦ湡鎬ф垨瀹氭椂浠诲姟
-     */
-    @Bean(name = "scheduledExecutorService")
-    protected ScheduledExecutorService scheduledExecutorService() {
-        return new ScheduledThreadPoolExecutor(core,
-            new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
-            new ThreadPoolExecutor.CallerRunsPolicy()) {
-            @Override
-            protected void afterExecute(Runnable r, Throwable t) {
-                super.afterExecute(r, t);
-                Threads.printException(r, t);
-            }
-        };
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/UndertowConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/UndertowConfig.java
deleted file mode 100644
index 64e745a..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/UndertowConfig.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.ruoyi.framework.config;
-
-import io.undertow.server.DefaultByteBufferPool;
-import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
-import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
-import org.springframework.boot.web.server.WebServerFactoryCustomizer;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Undertow 鑷畾涔夐厤缃�
- *
- * @author Lion Li
- */
-@Configuration
-public class UndertowConfig implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
-
-    /**
-     * 璁剧疆 Undertow 鐨� websocket 缂撳啿姹�
-     */
-    @Override
-    public void customize(UndertowServletWebServerFactory factory) {
-        // 榛樿涓嶇洿鎺ュ垎閰嶅唴瀛� 濡傛灉椤圭洰涓娇鐢ㄤ簡 websocket 寤鸿鐩存帴鍒嗛厤
-        factory.addDeploymentInfoCustomizers(deploymentInfo -> {
-            WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
-            webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 512));
-            deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
-        });
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ValidatorConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ValidatorConfig.java
deleted file mode 100644
index 654d4bc..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ValidatorConfig.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.ruoyi.framework.config;
-
-import org.hibernate.validator.HibernateValidator;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
-
-import jakarta.validation.Validator;
-import java.util.Properties;
-
-/**
- * 鏍¢獙妗嗘灦閰嶇疆绫�
- *
- * @author Lion Li
- */
-@Configuration
-public class ValidatorConfig {
-
-    @Autowired
-    private MessageSource messageSource;
-
-    /**
-     * 閰嶇疆鏍¢獙妗嗘灦 蹇�熻繑鍥炴ā寮�
-     */
-    @Bean
-    public Validator validator() {
-        LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
-        // 鍥介檯鍖�
-        factoryBean.setValidationMessageSource(messageSource);
-        // 璁剧疆浣跨敤 HibernateValidator 鏍¢獙鍣�
-        factoryBean.setProviderClass(HibernateValidator.class);
-        Properties properties = new Properties();
-        // 璁剧疆 蹇�熷紓甯歌繑鍥�
-        properties.setProperty("hibernate.validator.fail_fast", "true");
-        factoryBean.setValidationProperties(properties);
-        // 鍔犺浇閰嶇疆
-        factoryBean.afterPropertiesSet();
-        return factoryBean.getValidator();
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java
deleted file mode 100644
index 1b41c66..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import com.ruoyi.common.enums.CaptchaCategory;
-import com.ruoyi.common.enums.CaptchaType;
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * 楠岃瘉鐮� 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "captcha")
-public class CaptchaProperties {
-
-    /**
-     * 楠岃瘉鐮佺被鍨�
-     */
-    private CaptchaType type;
-
-    /**
-     * 楠岃瘉鐮佺被鍒�
-     */
-    private CaptchaCategory category;
-
-    /**
-     * 鏁板瓧楠岃瘉鐮佷綅鏁�
-     */
-    private Integer numberLength;
-
-    /**
-     * 瀛楃楠岃瘉鐮侀暱搴�
-     */
-    private Integer charLength;
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java
deleted file mode 100644
index 95e6cb8..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/MailProperties.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * JavaMail 閰嶇疆灞炴��
- *
- * @author Michelle.Chung
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "mail")
-public class MailProperties {
-
-    /**
-     * 杩囨护寮�鍏�
-     */
-    private Boolean enabled;
-
-    /**
-     * SMTP鏈嶅姟鍣ㄥ煙鍚�
-     */
-    private String host;
-
-    /**
-     * SMTP鏈嶅姟绔彛
-     */
-    private Integer port;
-
-    /**
-     * 鏄惁闇�瑕佺敤鎴峰悕瀵嗙爜楠岃瘉
-     */
-    private Boolean auth;
-
-    /**
-     * 鐢ㄦ埛鍚�
-     */
-    private String user;
-
-    /**
-     * 瀵嗙爜
-     */
-    private String pass;
-
-    /**
-     * 鍙戦�佹柟锛岄伒寰猂FC-822鏍囧噯
-     */
-    private String from;
-
-    /**
-     * 浣跨敤 STARTTLS瀹夊叏杩炴帴锛孲TARTTLS鏄绾枃鏈�氫俊鍗忚鐨勬墿灞曘�傚畠灏嗙函鏂囨湰杩炴帴鍗囩骇涓哄姞瀵嗚繛鎺ワ紙TLS鎴朣SL锛夛紝 鑰屼笉鏄娇鐢ㄤ竴涓崟鐙殑鍔犲瘑閫氫俊绔彛銆�
-     */
-    private Boolean starttlsEnable;
-
-    /**
-     * 浣跨敤 SSL瀹夊叏杩炴帴
-     */
-    private Boolean sslEnable;
-
-    /**
-     * SMTP瓒呮椂鏃堕暱锛屽崟浣嶆绉掞紝缂虹渷鍊间笉瓒呮椂
-     */
-    private Long timeout;
-
-    /**
-     * Socket杩炴帴瓒呮椂鍊硷紝鍗曚綅姣锛岀己鐪佸�间笉瓒呮椂
-     */
-    private Long connectionTimeout;
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java
deleted file mode 100644
index b0bf285..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.redisson.config.ReadMode;
-import org.redisson.config.SubscriptionMode;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * Redisson 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "redisson")
-public class RedissonProperties {
-
-    /**
-     * redis缂撳瓨key鍓嶇紑
-     */
-    private String keyPrefix;
-
-    /**
-     * 绾跨▼姹犳暟閲�,榛樿鍊� = 褰撳墠澶勭悊鏍告暟閲� * 2
-     */
-    private int threads;
-
-    /**
-     * Netty绾跨▼姹犳暟閲�,榛樿鍊� = 褰撳墠澶勭悊鏍告暟閲� * 2
-     */
-    private int nettyThreads;
-
-    /**
-     * 鍗曟満鏈嶅姟閰嶇疆
-     */
-    private SingleServerConfig singleServerConfig;
-
-    /**
-     * 闆嗙兢鏈嶅姟閰嶇疆
-     */
-    private ClusterServersConfig clusterServersConfig;
-
-    @Data
-    @NoArgsConstructor
-    public static class SingleServerConfig {
-
-        /**
-         * 瀹㈡埛绔悕绉�
-         */
-        private String clientName;
-
-        /**
-         * 鏈�灏忕┖闂茶繛鎺ユ暟
-         */
-        private int connectionMinimumIdleSize;
-
-        /**
-         * 杩炴帴姹犲ぇ灏�
-         */
-        private int connectionPoolSize;
-
-        /**
-         * 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
-         */
-        private int idleConnectionTimeout;
-
-        /**
-         * 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
-         */
-        private int timeout;
-
-        /**
-         * 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
-         */
-        private int subscriptionConnectionPoolSize;
-
-    }
-
-    @Data
-    @NoArgsConstructor
-    public static class ClusterServersConfig {
-
-        /**
-         * 瀹㈡埛绔悕绉�
-         */
-        private String clientName;
-
-        /**
-         * master鏈�灏忕┖闂茶繛鎺ユ暟
-         */
-        private int masterConnectionMinimumIdleSize;
-
-        /**
-         * master杩炴帴姹犲ぇ灏�
-         */
-        private int masterConnectionPoolSize;
-
-        /**
-         * slave鏈�灏忕┖闂茶繛鎺ユ暟
-         */
-        private int slaveConnectionMinimumIdleSize;
-
-        /**
-         * slave杩炴帴姹犲ぇ灏�
-         */
-        private int slaveConnectionPoolSize;
-
-        /**
-         * 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
-         */
-        private int idleConnectionTimeout;
-
-        /**
-         * 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
-         */
-        private int timeout;
-
-        /**
-         * 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
-         */
-        private int subscriptionConnectionPoolSize;
-
-        /**
-         * 璇诲彇妯″紡
-         */
-        private ReadMode readMode;
-
-        /**
-         * 璁㈤槄妯″紡
-         */
-        private SubscriptionMode subscriptionMode;
-
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SecurityProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SecurityProperties.java
deleted file mode 100644
index b374181..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SecurityProperties.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * Security 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "security")
-public class SecurityProperties {
-
-    /**
-     * 鎺掗櫎璺緞
-     */
-    private String[] excludes;
-
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java
deleted file mode 100644
index 736d70a..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import io.swagger.v3.oas.models.Components;
-import io.swagger.v3.oas.models.ExternalDocumentation;
-import io.swagger.v3.oas.models.Paths;
-import io.swagger.v3.oas.models.info.Contact;
-import io.swagger.v3.oas.models.info.License;
-import io.swagger.v3.oas.models.tags.Tag;
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.context.properties.NestedConfigurationProperty;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * swagger 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "swagger")
-public class SwaggerProperties {
-
-    /**
-     * 鏄惁寮�鍚� openApi 鏂囨。
-     */
-    private Boolean enabled = true;
-
-    /**
-     * 鏂囨。鍩烘湰淇℃伅
-     */
-    @NestedConfigurationProperty
-    private InfoProperties info = new InfoProperties();
-
-    /**
-     * 鎵╁睍鏂囨。鍦板潃
-     */
-    @NestedConfigurationProperty
-    private ExternalDocumentation externalDocs;
-
-    /**
-     * 鏍囩
-     */
-    private List<Tag> tags = null;
-
-    /**
-     * 璺緞
-     */
-    @NestedConfigurationProperty
-    private Paths paths = null;
-
-    /**
-     * 缁勪欢
-     */
-    @NestedConfigurationProperty
-    private Components components = null;
-
-    /**
-     * <p>
-     * 鏂囨。鐨勫熀纭�灞炴�т俊鎭�
-     * </p>
-     *
-     * @see io.swagger.v3.oas.models.info.Info
-     *
-     * 涓轰簡 springboot 鑷姩鐢熶骇閰嶇疆鎻愮ず淇℃伅锛屾墍浠ヨ繖閲屽鍒朵竴涓被鍑烘潵
-     */
-    @Data
-    public static class InfoProperties {
-
-        /**
-         * 鏍囬
-         */
-        private String title = null;
-
-        /**
-         * 鎻忚堪
-         */
-        private String description = null;
-
-        /**
-         * 鑱旂郴浜轰俊鎭�
-         */
-        @NestedConfigurationProperty
-        private Contact contact = null;
-
-        /**
-         * 璁稿彲璇�
-         */
-        @NestedConfigurationProperty
-        private License license = null;
-
-        /**
-         * 鐗堟湰
-         */
-        private String version = null;
-
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java
deleted file mode 100644
index fe06733..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * 绾跨▼姹� 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "thread-pool")
-public class ThreadPoolProperties {
-
-    /**
-     * 鏄惁寮�鍚嚎绋嬫睜
-     */
-    private boolean enabled;
-
-    /**
-     * 闃熷垪鏈�澶ч暱搴�
-     */
-    private int queueCapacity;
-
-    /**
-     * 绾跨▼姹犵淮鎶ょ嚎绋嬫墍鍏佽鐨勭┖闂叉椂闂�
-     */
-    private int keepAliveSeconds;
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java
deleted file mode 100644
index d8a68a8..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/XssProperties.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * xss杩囨护 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "xss")
-public class XssProperties {
-
-    /**
-     * 杩囨护寮�鍏�
-     */
-    private String enabled;
-
-    /**
-     * 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
-     */
-    private String excludes;
-
-    /**
-     * 鍖归厤閾炬帴
-     */
-    private String urlPatterns;
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/CreateAndUpdateMetaObjectHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/CreateAndUpdateMetaObjectHandler.java
deleted file mode 100644
index 6d7c977..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/CreateAndUpdateMetaObjectHandler.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.ruoyi.framework.handler;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.http.HttpStatus;
-import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.ibatis.reflection.MetaObject;
-
-import java.util.Date;
-
-/**
- * MP娉ㄥ叆澶勭悊鍣�
- *
- * @author Lion Li
- * @date 2021/4/25
- */
-@Slf4j
-public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {
-
-    @Override
-    public void insertFill(MetaObject metaObject) {
-        try {
-            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
-                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
-                Date current = ObjectUtil.isNotNull(baseEntity.getCreateTime())
-                    ? baseEntity.getCreateTime() : new Date();
-                baseEntity.setCreateTime(current);
-                baseEntity.setUpdateTime(current);
-                String username = StringUtils.isNotBlank(baseEntity.getCreateBy())
-                    ? baseEntity.getCreateBy() : getLoginUsername();
-                // 褰撳墠宸茬櫥褰� 涓� 鍒涘缓浜轰负绌� 鍒欏~鍏�
-                baseEntity.setCreateBy(username);
-                // 褰撳墠宸茬櫥褰� 涓� 鏇存柊浜轰负绌� 鍒欏~鍏�
-                baseEntity.setUpdateBy(username);
-            }
-        } catch (Exception e) {
-            throw new ServiceException("鑷姩娉ㄥ叆寮傚父 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
-        }
-    }
-
-    @Override
-    public void updateFill(MetaObject metaObject) {
-        try {
-            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
-                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
-                Date current = new Date();
-                // 鏇存柊鏃堕棿濉厖(涓嶇涓轰笉涓虹┖)
-                baseEntity.setUpdateTime(current);
-                String username = getLoginUsername();
-                // 褰撳墠宸茬櫥褰� 鏇存柊浜哄~鍏�(涓嶇涓轰笉涓虹┖)
-                if (StringUtils.isNotBlank(username)) {
-                    baseEntity.setUpdateBy(username);
-                }
-            }
-        } catch (Exception e) {
-            throw new ServiceException("鑷姩娉ㄥ叆寮傚父 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
-        }
-    }
-
-    /**
-     * 鑾峰彇鐧诲綍鐢ㄦ埛鍚�
-     */
-    private String getLoginUsername() {
-        LoginUser loginUser;
-        try {
-            loginUser = LoginHelper.getLoginUser();
-        } catch (Exception e) {
-            log.warn("鑷姩娉ㄥ叆璀﹀憡 => 鐢ㄦ埛鏈櫥褰�");
-            return null;
-        }
-        return loginUser.getUsername();
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/KeyPrefixHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/KeyPrefixHandler.java
deleted file mode 100644
index 161c271..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/KeyPrefixHandler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.ruoyi.framework.handler;
-
-import com.ruoyi.common.utils.StringUtils;
-import org.redisson.api.NameMapper;
-
-/**
- * redis缂撳瓨key鍓嶇紑澶勭悊
- *
- * @author ye
- * @date 2022/7/14 17:44
- * @since 4.3.0
- */
-public class KeyPrefixHandler implements NameMapper {
-
-    private final String keyPrefix;
-
-    public KeyPrefixHandler(String keyPrefix) {
-        //鍓嶇紑涓虹┖ 鍒欒繑鍥炵┖鍓嶇紑
-        this.keyPrefix = StringUtils.isBlank(keyPrefix) ? "" : keyPrefix + ":";
-    }
-
-    /**
-     * 澧炲姞鍓嶇紑
-     */
-    @Override
-    public String map(String name) {
-        if (StringUtils.isBlank(name)) {
-            return null;
-        }
-        if (StringUtils.isNotBlank(keyPrefix) && !name.startsWith(keyPrefix)) {
-            return keyPrefix + name;
-        }
-        return name;
-    }
-
-    /**
-     * 鍘婚櫎鍓嶇紑
-     */
-    @Override
-    public String unmap(String name) {
-        if (StringUtils.isBlank(name)) {
-            return null;
-        }
-        if (StringUtils.isNotBlank(keyPrefix) && name.startsWith(keyPrefix)) {
-            return name.substring(keyPrefix.length());
-        }
-        return name;
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/OpenApiHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/OpenApiHandler.java
deleted file mode 100644
index 3bb239e..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/OpenApiHandler.java
+++ /dev/null
@@ -1,252 +0,0 @@
-package com.ruoyi.framework.handler;
-
-import cn.hutool.core.io.IoUtil;
-import io.swagger.v3.core.jackson.TypeNameResolver;
-import io.swagger.v3.core.util.AnnotationsUtils;
-import io.swagger.v3.oas.annotations.tags.Tags;
-import io.swagger.v3.oas.models.Components;
-import io.swagger.v3.oas.models.OpenAPI;
-import io.swagger.v3.oas.models.Operation;
-import io.swagger.v3.oas.models.Paths;
-import io.swagger.v3.oas.models.tags.Tag;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
-import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
-import org.springdoc.core.properties.SpringDocConfigProperties;
-import org.springdoc.core.providers.JavadocProvider;
-import org.springdoc.core.service.OpenAPIService;
-import org.springdoc.core.service.SecurityService;
-import org.springdoc.core.utils.PropertyResolverUtils;
-import org.springframework.context.ApplicationContext;
-import org.springframework.core.annotation.AnnotatedElementUtils;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.method.HandlerMethod;
-
-import java.io.StringReader;
-import java.lang.reflect.Method;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * 鑷畾涔� openapi 澶勭悊鍣�
- * 瀵规簮鐮佸姛鑳借繘琛屼慨鏀� 澧炲己浣跨敤
- */
-@Slf4j
-@SuppressWarnings("all")
-public class OpenApiHandler extends OpenAPIService {
-
-    /**
-     * The Basic error controller.
-     */
-    private static Class<?> basicErrorController;
-
-    /**
-     * The Security parser.
-     */
-    private final SecurityService securityParser;
-
-    /**
-     * The Mappings map.
-     */
-    private final Map<String, Object> mappingsMap = new HashMap<>();
-
-    /**
-     * The Springdoc tags.
-     */
-    private final Map<HandlerMethod, Tag> springdocTags = new HashMap<>();
-
-    /**
-     * The Open api builder customisers.
-     */
-    private final Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers;
-
-    /**
-     * The server base URL customisers.
-     */
-    private final Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers;
-
-    /**
-     * The Spring doc config properties.
-     */
-    private final SpringDocConfigProperties springDocConfigProperties;
-
-    /**
-     * The Cached open api map.
-     */
-    private final Map<String, OpenAPI> cachedOpenAPI = new HashMap<>();
-
-    /**
-     * The Property resolver utils.
-     */
-    private final PropertyResolverUtils propertyResolverUtils;
-
-    /**
-     * The javadoc provider.
-     */
-    private final Optional<JavadocProvider> javadocProvider;
-
-    /**
-     * The Context.
-     */
-    private ApplicationContext context;
-
-    /**
-     * The Open api.
-     */
-    private OpenAPI openAPI;
-
-    /**
-     * The Is servers present.
-     */
-    private boolean isServersPresent;
-
-    /**
-     * The Server base url.
-     */
-    private String serverBaseUrl;
-
-    /**
-     * Instantiates a new Open api builder.
-     *
-     * @param openAPI                   the open api
-     * @param securityParser            the security parser
-     * @param springDocConfigProperties the spring doc config properties
-     * @param propertyResolverUtils     the property resolver utils
-     * @param openApiBuilderCustomizers the open api builder customisers
-     * @param serverBaseUrlCustomizers  the server base url customizers
-     * @param javadocProvider           the javadoc provider
-     */
-    public OpenApiHandler(Optional<OpenAPI> openAPI, SecurityService securityParser,
-                          SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
-                          Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
-                          Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
-                          Optional<JavadocProvider> javadocProvider) {
-        super(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);
-        if (openAPI.isPresent()) {
-            this.openAPI = openAPI.get();
-            if (this.openAPI.getComponents() == null)
-                this.openAPI.setComponents(new Components());
-            if (this.openAPI.getPaths() == null)
-                this.openAPI.setPaths(new Paths());
-            if (!CollectionUtils.isEmpty(this.openAPI.getServers()))
-                this.isServersPresent = true;
-        }
-        this.propertyResolverUtils = propertyResolverUtils;
-        this.securityParser = securityParser;
-        this.springDocConfigProperties = springDocConfigProperties;
-        this.openApiBuilderCustomisers = openApiBuilderCustomizers;
-        this.serverBaseUrlCustomizers = serverBaseUrlCustomizers;
-        this.javadocProvider = javadocProvider;
-        if (springDocConfigProperties.isUseFqn())
-            TypeNameResolver.std.setUseFqn(true);
-    }
-
-    @Override
-    public Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) {
-
-        Set<Tag> tags = new HashSet<>();
-        Set<String> tagsStr = new HashSet<>();
-
-        buildTagsFromMethod(handlerMethod.getMethod(), tags, tagsStr, locale);
-        buildTagsFromClass(handlerMethod.getBeanType(), tags, tagsStr, locale);
-
-        if (!CollectionUtils.isEmpty(tagsStr))
-            tagsStr = tagsStr.stream()
-                .map(str -> propertyResolverUtils.resolve(str, locale))
-                .collect(Collectors.toSet());
-
-        if (springdocTags.containsKey(handlerMethod)) {
-            io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod);
-            tagsStr.add(tag.getName());
-            if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
-                openAPI.addTagsItem(tag);
-            }
-        }
-
-        if (!CollectionUtils.isEmpty(tagsStr)) {
-            if (CollectionUtils.isEmpty(operation.getTags()))
-                operation.setTags(new ArrayList<>(tagsStr));
-            else {
-                Set<String> operationTagsSet = new HashSet<>(operation.getTags());
-                operationTagsSet.addAll(tagsStr);
-                operation.getTags().clear();
-                operation.getTags().addAll(operationTagsSet);
-            }
-        }
-
-        if (isAutoTagClasses(operation)) {
-
-
-            if (javadocProvider.isPresent()) {
-                String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType());
-                if (StringUtils.isNotBlank(description)) {
-                    io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.Tag();
-
-                    // 鑷畾涔夐儴鍒� 淇敼浣跨敤java娉ㄩ噴褰搕ag鍚�
-                    List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>());
-                    // tag.setName(tagAutoName);
-                    tag.setName(list.get(0));
-                    operation.addTagsItem(list.get(0));
-
-                    tag.setDescription(description);
-                    if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
-                        openAPI.addTagsItem(tag);
-                    }
-                }
-            } else {
-                String tagAutoName = splitCamelCase(handlerMethod.getBeanType().getSimpleName());
-                operation.addTagsItem(tagAutoName);
-            }
-        }
-
-        if (!CollectionUtils.isEmpty(tags)) {
-            // Existing tags
-            List<io.swagger.v3.oas.models.tags.Tag> openApiTags = openAPI.getTags();
-            if (!CollectionUtils.isEmpty(openApiTags))
-                tags.addAll(openApiTags);
-            openAPI.setTags(new ArrayList<>(tags));
-        }
-
-        // Handle SecurityRequirement at operation level
-        io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser
-            .getSecurityRequirements(handlerMethod);
-        if (securityRequirements != null) {
-            if (securityRequirements.length == 0)
-                operation.setSecurity(Collections.emptyList());
-            else
-                securityParser.buildSecurityRequirement(securityRequirements, operation);
-        }
-
-        return operation;
-    }
-
-    private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) {
-        // method tags
-        Set<Tags> tagsSet = AnnotatedElementUtils
-            .findAllMergedAnnotations(method, Tags.class);
-        Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream()
-            .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet());
-        methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class));
-        if (!CollectionUtils.isEmpty(methodTags)) {
-            tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet()));
-            List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags);
-            addTags(allTags, tags, locale);
-        }
-    }
-
-    private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag> tags, Locale locale) {
-        Optional<Set<io.swagger.v3.oas.models.tags.Tag>> optionalTagSet = AnnotationsUtils
-            .getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true);
-        optionalTagSet.ifPresent(tagsSet -> {
-            tagsSet.forEach(tag -> {
-                tag.name(propertyResolverUtils.resolve(tag.getName(), locale));
-                tag.description(propertyResolverUtils.resolve(tag.getDescription(), locale));
-                if (tags.stream().noneMatch(t -> t.getName().equals(tag.getName())))
-                    tags.add(tag);
-            });
-        });
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java
deleted file mode 100644
index 3825a0b..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.ruoyi.framework.handler;
-
-import cn.hutool.core.annotation.AnnotationUtil;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.ConcurrentHashSet;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ClassUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.annotation.DataColumn;
-import com.ruoyi.common.annotation.DataPermission;
-import com.ruoyi.common.core.domain.dto.RoleDTO;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.enums.DataScopeType;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.DataPermissionHelper;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-import net.sf.jsqlparser.JSQLParserException;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.Parenthesis;
-import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
-import net.sf.jsqlparser.parser.CCJSqlParserUtil;
-import org.springframework.context.expression.BeanFactoryResolver;
-import org.springframework.expression.BeanResolver;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.ParserContext;
-import org.springframework.expression.common.TemplateParserContext;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
-
-import java.lang.reflect.Method;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * 鏁版嵁鏉冮檺杩囨护
- *
- * @author Lion Li
- * @version 3.5.0
- */
-@Slf4j
-public class PlusDataPermissionHandler {
-
-    /**
-     * 鏂规硶鎴栫被(鍚嶇О) 涓� 娉ㄨВ鐨勬槧灏勫叧绯荤紦瀛�
-     */
-    private final Map<String, DataPermission> dataPermissionCacheMap = new ConcurrentHashMap<>();
-
-    /**
-     * 鏃犳晥娉ㄨВ鏂规硶缂撳瓨鐢ㄤ簬蹇�熻繑鍥�
-     */
-    private final Set<String> invalidCacheSet = new ConcurrentHashSet<>();
-
-    /**
-     * spel 瑙f瀽鍣�
-     */
-    private final ExpressionParser parser = new SpelExpressionParser();
-    private final ParserContext parserContext = new TemplateParserContext();
-    /**
-     * bean瑙f瀽鍣� 鐢ㄤ簬澶勭悊 spel 琛ㄨ揪寮忎腑瀵� bean 鐨勮皟鐢�
-     */
-    private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory());
-
-
-    public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) {
-        DataColumn[] dataColumns = findAnnotation(mappedStatementId);
-        if (ArrayUtil.isEmpty(dataColumns)) {
-            invalidCacheSet.add(mappedStatementId);
-            return where;
-        }
-        LoginUser currentUser = DataPermissionHelper.getVariable("user");
-        if (ObjectUtil.isNull(currentUser)) {
-            currentUser = LoginHelper.getLoginUser();
-            DataPermissionHelper.setVariable("user", currentUser);
-        }
-        // 濡傛灉鏄秴绾х鐞嗗憳锛屽垯涓嶈繃婊ゆ暟鎹�
-        if (LoginHelper.isAdmin()) {
-            return where;
-        }
-        String dataFilterSql = buildDataFilter(dataColumns, isSelect);
-        if (StringUtils.isBlank(dataFilterSql)) {
-            return where;
-        }
-        try {
-            Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql);
-            // 鏁版嵁鏉冮檺浣跨敤鍗曠嫭鐨勬嫭鍙� 闃叉涓庡叾浠栨潯浠跺啿绐�
-            Parenthesis parenthesis = new Parenthesis(expression);
-            if (ObjectUtil.isNotNull(where)) {
-                return new AndExpression(where, parenthesis);
-            } else {
-                return parenthesis;
-            }
-        } catch (JSQLParserException e) {
-            throw new ServiceException("鏁版嵁鏉冮檺瑙f瀽寮傚父 => " + e.getMessage());
-        }
-    }
-
-    /**
-     * 鏋勯�犳暟鎹繃婊ql
-     */
-    private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) {
-        // 鏇存柊鎴栧垹闄ら渶婊¤冻鎵�鏈夋潯浠�
-        String joinStr = isSelect ? " OR " : " AND ";
-        LoginUser user = DataPermissionHelper.getVariable("user");
-        StandardEvaluationContext context = new StandardEvaluationContext();
-        context.setBeanResolver(beanResolver);
-        DataPermissionHelper.getContext().forEach(context::setVariable);
-        Set<String> conditions = new HashSet<>();
-        for (RoleDTO role : user.getRoles()) {
-            user.setRoleId(role.getRoleId());
-            // 鑾峰彇瑙掕壊鏉冮檺娉涘瀷
-            DataScopeType type = DataScopeType.findCode(role.getDataScope());
-            if (ObjectUtil.isNull(type)) {
-                throw new ServiceException("瑙掕壊鏁版嵁鑼冨洿寮傚父 => " + role.getDataScope());
-            }
-            // 鍏ㄩ儴鏁版嵁鏉冮檺鐩存帴杩斿洖
-            if (type == DataScopeType.ALL) {
-                return "";
-            }
-            boolean isSuccess = false;
-            for (DataColumn dataColumn : dataColumns) {
-                if (dataColumn.key().length != dataColumn.value().length) {
-                    throw new ServiceException("瑙掕壊鏁版嵁鑼冨洿寮傚父 => key涓巚alue闀垮害涓嶅尮閰�");
-                }
-                // 涓嶅寘鍚� key 鍙橀噺 鍒欎笉澶勭悊
-                if (!StringUtils.containsAny(type.getSqlTemplate(),
-                    Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new)
-                )) {
-                    continue;
-                }
-                // 璁剧疆娉ㄨВ鍙橀噺 key 涓鸿〃杈惧紡鍙橀噺 value 涓哄彉閲忓��
-                for (int i = 0; i < dataColumn.key().length; i++) {
-                    context.setVariable(dataColumn.key()[i], dataColumn.value()[i]);
-                }
-
-                // 瑙f瀽sql妯℃澘骞跺~鍏�
-                String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class);
-                conditions.add(joinStr + sql);
-                isSuccess = true;
-            }
-            // 鏈鐞嗘垚鍔熷垯濉厖鍏滃簳鏂规
-            if (!isSuccess && StringUtils.isNotBlank(type.getElseSql())) {
-                conditions.add(joinStr + type.getElseSql());
-            }
-        }
-
-        if (CollUtil.isNotEmpty(conditions)) {
-            String sql = StreamUtils.join(conditions, Function.identity(), "");
-            return sql.substring(joinStr.length());
-        }
-        return "";
-    }
-
-    private DataColumn[] findAnnotation(String mappedStatementId) {
-        StringBuilder sb = new StringBuilder(mappedStatementId);
-        int index = sb.lastIndexOf(".");
-        String clazzName = sb.substring(0, index);
-        String methodName = sb.substring(index + 1, sb.length());
-        Class<?> clazz = ClassUtil.loadClass(clazzName);
-        List<Method> methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz))
-            .filter(method -> method.getName().equals(methodName)).collect(Collectors.toList());
-        DataPermission dataPermission;
-        // 鑾峰彇鏂规硶娉ㄨВ
-        for (Method method : methods) {
-            dataPermission = dataPermissionCacheMap.get(mappedStatementId);
-            if (ObjectUtil.isNotNull(dataPermission)) {
-                return dataPermission.value();
-            }
-            if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) {
-                dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class);
-                dataPermissionCacheMap.put(mappedStatementId, dataPermission);
-                return dataPermission.value();
-            }
-        }
-        dataPermission = dataPermissionCacheMap.get(clazz.getName());
-        if (ObjectUtil.isNotNull(dataPermission)) {
-            return dataPermission.value();
-        }
-        // 鑾峰彇绫绘敞瑙�
-        if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) {
-            dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class);
-            dataPermissionCacheMap.put(clazz.getName(), dataPermission);
-            return dataPermission.value();
-        }
-        return null;
-    }
-
-    /**
-     * 鏄惁涓烘棤鏁堟柟娉� 鏃犳暟鎹潈闄�
-     */
-    public boolean isInvalid(String mappedStatementId) {
-        return invalidCacheSet.contains(mappedStatementId);
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusDataPermissionInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusDataPermissionInterceptor.java
deleted file mode 100644
index 508f421..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusDataPermissionInterceptor.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.ruoyi.framework.interceptor;
-
-import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
-import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
-import com.ruoyi.framework.handler.PlusDataPermissionHandler;
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.statement.delete.Delete;
-import net.sf.jsqlparser.statement.select.PlainSelect;
-import net.sf.jsqlparser.statement.select.Select;
-import net.sf.jsqlparser.statement.select.SelectBody;
-import net.sf.jsqlparser.statement.select.SetOperationList;
-import net.sf.jsqlparser.statement.update.Update;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.session.ResultHandler;
-import org.apache.ibatis.session.RowBounds;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.List;
-
-/**
- * 鏁版嵁鏉冮檺鎷︽埅鍣�
- *
- * @author Lion Li
- * @version 3.5.0
- */
-public class PlusDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
-
-    private final PlusDataPermissionHandler dataPermissionHandler = new PlusDataPermissionHandler();
-
-    @Override
-    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
-        // 妫�鏌ュ拷鐣ユ敞瑙�
-        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
-            return;
-        }
-        // 妫�鏌ユ槸鍚︽棤鏁� 鏃犳暟鎹潈闄愭敞瑙�
-        if (dataPermissionHandler.isInvalid(ms.getId())) {
-            return;
-        }
-        // 瑙f瀽 sql 鍒嗛厤瀵瑰簲鏂规硶
-        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
-        mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));
-    }
-
-    @Override
-    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
-        PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
-        MappedStatement ms = mpSh.mappedStatement();
-        SqlCommandType sct = ms.getSqlCommandType();
-        if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
-            if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
-                return;
-            }
-            PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
-            mpBs.sql(parserMulti(mpBs.sql(), ms.getId()));
-        }
-    }
-
-    @Override
-    protected void processSelect(Select select, int index, String sql, Object obj) {
-        SelectBody selectBody = select.getSelectBody();
-        if (selectBody instanceof PlainSelect) {
-            this.setWhere((PlainSelect) selectBody, (String) obj);
-        } else if (selectBody instanceof SetOperationList) {
-            SetOperationList setOperationList = (SetOperationList) selectBody;
-            List<SelectBody> selectBodyList = setOperationList.getSelects();
-            selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
-        }
-    }
-
-    @Override
-    protected void processUpdate(Update update, int index, String sql, Object obj) {
-        Expression sqlSegment = dataPermissionHandler.getSqlSegment(update.getWhere(), (String) obj, false);
-        if (null != sqlSegment) {
-            update.setWhere(sqlSegment);
-        }
-    }
-
-    @Override
-    protected void processDelete(Delete delete, int index, String sql, Object obj) {
-        Expression sqlSegment = dataPermissionHandler.getSqlSegment(delete.getWhere(), (String) obj, false);
-        if (null != sqlSegment) {
-            delete.setWhere(sqlSegment);
-        }
-    }
-
-    /**
-     * 璁剧疆 where 鏉′欢
-     *
-     * @param plainSelect       鏌ヨ瀵硅薄
-     * @param mappedStatementId 鎵ц鏂规硶id
-     */
-    protected void setWhere(PlainSelect plainSelect, String mappedStatementId) {
-        Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), mappedStatementId, true);
-        if (null != sqlSegment) {
-            plainSelect.setWhere(sqlSegment);
-        }
-    }
-
-}
-
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java
deleted file mode 100644
index 70fa688..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.ruoyi.framework.interceptor;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.map.MapUtil;
-import com.alibaba.ttl.TransmittableThreadLocal;
-import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.time.StopWatch;
-import org.springframework.http.MediaType;
-import org.springframework.web.servlet.HandlerInterceptor;
-import org.springframework.web.servlet.ModelAndView;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.BufferedReader;
-import java.util.Map;
-
-/**
- * web鐨勮皟鐢ㄦ椂闂寸粺璁℃嫤鎴櫒
- * dev鐜鏈夋晥
- *
- * @author Lion Li
- * @since 3.3.0
- */
-@Slf4j
-public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
-
-    private final String prodProfile = "prod";
-
-    private final TransmittableThreadLocal<StopWatch> invokeTimeTL = new TransmittableThreadLocal<>();
-
-    @Override
-    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-        if (!prodProfile.equals(SpringUtils.getActiveProfile())) {
-            String url = request.getMethod() + " " + request.getRequestURI();
-
-            // 鎵撳嵃璇锋眰鍙傛暟
-            if (isJsonRequest(request)) {
-                String jsonParam = "";
-                if (request instanceof RepeatedlyRequestWrapper) {
-                    BufferedReader reader = request.getReader();
-                    jsonParam = IoUtil.read(reader);
-                }
-                log.debug("[PLUS]寮�濮嬭姹� => URL[{}],鍙傛暟绫诲瀷[json],鍙傛暟:[{}]", url, jsonParam);
-            } else {
-                Map<String, String[]> parameterMap = request.getParameterMap();
-                if (MapUtil.isNotEmpty(parameterMap)) {
-                    String parameters = JsonUtils.toJsonString(parameterMap);
-                    log.debug("[PLUS]寮�濮嬭姹� => URL[{}],鍙傛暟绫诲瀷[param],鍙傛暟:[{}]", url, parameters);
-                } else {
-                    log.debug("[PLUS]寮�濮嬭姹� => URL[{}],鏃犲弬鏁�", url);
-                }
-            }
-
-            StopWatch stopWatch = new StopWatch();
-            invokeTimeTL.set(stopWatch);
-            stopWatch.start();
-        }
-        return true;
-    }
-
-    @Override
-    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
-
-    }
-
-    @Override
-    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
-        if (!prodProfile.equals(SpringUtils.getActiveProfile())) {
-            StopWatch stopWatch = invokeTimeTL.get();
-            stopWatch.stop();
-            log.debug("[PLUS]缁撴潫璇锋眰 => URL[{}],鑰楁椂:[{}]姣", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime());
-            invokeTimeTL.remove();
-        }
-    }
-
-    /**
-     * 鍒ゆ柇鏈璇锋眰鐨勬暟鎹被鍨嬫槸鍚︿负json
-     *
-     * @param request request
-     * @return boolean
-     */
-    private boolean isJsonRequest(HttpServletRequest request) {
-        String contentType = request.getContentType();
-        if (contentType != null) {
-            return StringUtils.startsWithIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE);
-        }
-        return false;
-    }
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/jackson/BigNumberSerializer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/jackson/BigNumberSerializer.java
deleted file mode 100644
index a4aee15..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/jackson/BigNumberSerializer.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.ruoyi.framework.jackson;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-import com.fasterxml.jackson.databind.ser.std.NumberSerializer;
-
-import java.io.IOException;
-
-/**
- * 瓒呭嚭 JS 鏈�澶ф渶灏忓�� 澶勭悊
- *
- * @author Lion Li
- */
-@JacksonStdImpl
-public class BigNumberSerializer extends NumberSerializer {
-
-    /**
-     * 鏍规嵁 JS Number.MAX_SAFE_INTEGER 涓� Number.MIN_SAFE_INTEGER 寰楁潵
-     */
-    private static final long MAX_SAFE_INTEGER = 9007199254740991L;
-    private static final long MIN_SAFE_INTEGER = -9007199254740991L;
-
-    /**
-     * 鎻愪緵瀹炰緥
-     */
-    public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class);
-
-    public BigNumberSerializer(Class<? extends Number> rawType) {
-        super(rawType);
-    }
-
-    @Override
-    public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {
-        // 瓒呭嚭鑼冨洿 搴忓垪鍖栦綅瀛楃涓�
-        if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
-            super.serialize(value, gen, provider);
-        } else {
-            gen.writeString(value.toString());
-        }
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java
deleted file mode 100644
index a9de17e..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package com.ruoyi.framework.listener;
-
-import cn.dev33.satoken.config.SaTokenConfig;
-import cn.dev33.satoken.listener.SaTokenListener;
-import cn.dev33.satoken.stp.SaLoginModel;
-import cn.hutool.http.useragent.UserAgent;
-import cn.hutool.http.useragent.UserAgentUtil;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.enums.UserType;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.ip.AddressUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.time.Duration;
-
-/**
- * 鐢ㄦ埛琛屼负 渚﹀惉鍣ㄧ殑瀹炵幇
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Component
-@Slf4j
-public class UserActionListener implements SaTokenListener {
-
-    private final SaTokenConfig tokenConfig;
-
-    /**
-     * 姣忔鐧诲綍鏃惰Е鍙�
-     */
-    @Override
-    public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
-        UserType userType = UserType.getUserType(loginId.toString());
-        if (userType == UserType.SYS_USER) {
-            UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
-            String ip = ServletUtils.getClientIP();
-            LoginUser user = LoginHelper.getLoginUser();
-            UserOnlineDTO dto = new UserOnlineDTO();
-            dto.setIpaddr(ip);
-            dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
-            dto.setBrowser(userAgent.getBrowser().getName());
-            dto.setOs(userAgent.getOs().getName());
-            dto.setLoginTime(System.currentTimeMillis());
-            dto.setTokenId(tokenValue);
-            dto.setUserName(user.getUsername());
-            dto.setDeptName(user.getDeptName());
-            if(tokenConfig.getTimeout() == -1) {
-                RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto);
-            } else {
-                RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout()));
-            }
-            log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
-        } else if (userType == UserType.APP_USER) {
-            // app绔� 鑷鏍规嵁涓氬姟缂栧啓
-        }
-    }
-
-    /**
-     * 姣忔娉ㄩ攢鏃惰Е鍙�
-     */
-    @Override
-    public void doLogout(String loginType, Object loginId, String tokenValue) {
-        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
-        log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue);
-    }
-
-    /**
-     * 姣忔琚涪涓嬬嚎鏃惰Е鍙�
-     */
-    @Override
-    public void doKickout(String loginType, Object loginId, String tokenValue) {
-        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
-        log.info("user doLogoutByLoginId, userId:{}, token:{}", loginId, tokenValue);
-    }
-
-    /**
-     * 姣忔琚《涓嬬嚎鏃惰Е鍙�
-     */
-    @Override
-    public void doReplaced(String loginType, Object loginId, String tokenValue) {
-        RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue);
-        log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue);
-    }
-
-    /**
-     * 姣忔琚皝绂佹椂瑙﹀彂
-     */
-    @Override
-    public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
-    }
-
-    /**
-     * 姣忔琚В灏佹椂瑙﹀彂
-     */
-    @Override
-    public void doUntieDisable(String loginType, Object loginId, String service) {
-    }
-
-    /**
-     * 姣忔鎵撳紑浜岀骇璁よ瘉鏃惰Е鍙�
-     */
-    @Override
-    public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
-    }
-
-    /**
-     * 姣忔鍒涘缓Session鏃惰Е鍙�
-     */
-    @Override
-    public void doCloseSafe(String loginType, String tokenValue, String service) {
-    }
-
-    /**
-     * 姣忔鍒涘缓Session鏃惰Е鍙�
-     */
-    @Override
-    public void doCreateSession(String id) {
-    }
-
-    /**
-     * 姣忔娉ㄩ攢Session鏃惰Е鍙�
-     */
-    @Override
-    public void doLogoutSession(String id) {
-    }
-
-    /**
-     * 姣忔Token缁湡鏃惰Е鍙�
-     */
-    @Override
-    public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/PlusSpringCacheManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/PlusSpringCacheManager.java
deleted file mode 100644
index d8bfce7..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/PlusSpringCacheManager.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * Copyright (c) 2013-2021 Nikita Koksharov
- *
- * 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
- *
- *    http://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 com.ruoyi.framework.manager;
-
-import com.ruoyi.common.utils.redis.RedisUtils;
-import org.redisson.api.RMap;
-import org.redisson.api.RMapCache;
-import org.redisson.spring.cache.CacheConfig;
-import org.redisson.spring.cache.RedissonCache;
-import org.springframework.boot.convert.DurationStyle;
-import org.springframework.cache.Cache;
-import org.springframework.cache.CacheManager;
-import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
-import org.springframework.util.StringUtils;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * A {@link org.springframework.cache.CacheManager} implementation
- * backed by Redisson instance.
- * <p>
- * 淇敼 RedissonSpringCacheManager 婧愮爜
- * 閲嶅啓 cacheName 澶勭悊鏂规硶 鏀寔澶氬弬鏁�
- *
- * @author Nikita Koksharov
- *
- */
-@SuppressWarnings("unchecked")
-public class PlusSpringCacheManager implements CacheManager {
-
-    private boolean dynamic = true;
-
-    private boolean allowNullValues = true;
-
-    private boolean transactionAware = true;
-
-    Map<String, CacheConfig> configMap = new ConcurrentHashMap<>();
-    ConcurrentMap<String, Cache> instanceMap = new ConcurrentHashMap<>();
-
-    /**
-     * Creates CacheManager supplied by Redisson instance
-     */
-    public PlusSpringCacheManager() {
-    }
-
-
-    /**
-     * Defines possibility of storing {@code null} values.
-     * <p>
-     * Default is <code>true</code>
-     *
-     * @param allowNullValues stores if <code>true</code>
-     */
-    public void setAllowNullValues(boolean allowNullValues) {
-        this.allowNullValues = allowNullValues;
-    }
-
-    /**
-     * Defines if cache aware of Spring-managed transactions.
-     * If {@code true} put/evict operations are executed only for successful transaction in after-commit phase.
-     * <p>
-     * Default is <code>false</code>
-     *
-     * @param transactionAware cache is transaction aware if <code>true</code>
-     */
-    public void setTransactionAware(boolean transactionAware) {
-        this.transactionAware = transactionAware;
-    }
-
-    /**
-     * Defines 'fixed' cache names.
-     * A new cache instance will not be created in dynamic for non-defined names.
-     * <p>
-     * `null` parameter setups dynamic mode
-     *
-     * @param names of caches
-     */
-    public void setCacheNames(Collection<String> names) {
-        if (names != null) {
-            for (String name : names) {
-                getCache(name);
-            }
-            dynamic = false;
-        } else {
-            dynamic = true;
-        }
-    }
-
-    /**
-     * Set cache config mapped by cache name
-     *
-     * @param config object
-     */
-    public void setConfig(Map<String, ? extends CacheConfig> config) {
-        this.configMap = (Map<String, CacheConfig>) config;
-    }
-
-    protected CacheConfig createDefaultConfig() {
-        return new CacheConfig();
-    }
-
-    @Override
-    public Cache getCache(String name) {
-        Cache cache = instanceMap.get(name);
-        if (cache != null) {
-            return cache;
-        }
-        if (!dynamic) {
-            return cache;
-        }
-
-        CacheConfig config = configMap.get(name);
-        if (config == null) {
-            config = createDefaultConfig();
-            configMap.put(name, config);
-        }
-
-        // 閲嶅啓 cacheName 鏀寔澶氬弬鏁�
-        String[] array = StringUtils.delimitedListToStringArray(name, "#");
-        name = array[0];
-        if (array.length > 1) {
-            config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis());
-        }
-        if (array.length > 2) {
-            config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis());
-        }
-        if (array.length > 3) {
-            config.setMaxSize(Integer.parseInt(array[3]));
-        }
-
-        if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {
-            return createMap(name, config);
-        }
-
-        return createMapCache(name, config);
-    }
-
-    private Cache createMap(String name, CacheConfig config) {
-        RMap<Object, Object> map = RedisUtils.getClient().getMap(name);
-
-        Cache cache = new RedissonCache(map, allowNullValues);
-        if (transactionAware) {
-            cache = new TransactionAwareCacheDecorator(cache);
-        }
-        Cache oldCache = instanceMap.putIfAbsent(name, cache);
-        if (oldCache != null) {
-            cache = oldCache;
-        }
-        return cache;
-    }
-
-    private Cache createMapCache(String name, CacheConfig config) {
-        RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);
-
-        Cache cache = new RedissonCache(map, config, allowNullValues);
-        if (transactionAware) {
-            cache = new TransactionAwareCacheDecorator(cache);
-        }
-        Cache oldCache = instanceMap.putIfAbsent(name, cache);
-        if (oldCache != null) {
-            cache = oldCache;
-        } else {
-            map.setMaxSize(config.getMaxSize());
-        }
-        return cache;
-    }
-
-    @Override
-    public Collection<String> getCacheNames() {
-        return Collections.unmodifiableSet(configMap.keySet());
-    }
-
-
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
deleted file mode 100644
index 03d7603..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.framework.manager;
-
-import com.ruoyi.common.utils.Threads;
-import jakarta.annotation.PreDestroy;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Component;
-
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * 纭繚搴旂敤閫�鍑烘椂鑳藉叧闂悗鍙扮嚎绋�
- *
- * @author Lion Li
- */
-@Slf4j
-@Component
-public class ShutdownManager {
-
-    @Autowired
-    @Qualifier("scheduledExecutorService")
-    private ScheduledExecutorService scheduledExecutorService;
-
-    @PreDestroy
-    public void destroy() {
-        shutdownAsyncManager();
-    }
-
-    /**
-     * 鍋滄寮傛鎵ц浠诲姟
-     */
-    private void shutdownAsyncManager() {
-        try {
-            log.info("====鍏抽棴鍚庡彴浠诲姟浠诲姟绾跨▼姹�====");
-            Threads.shutdownAndAwaitTermination(scheduledExecutorService);
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-        }
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java
deleted file mode 100644
index 83c3d54..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package com.ruoyi.framework.satoken.dao;
-
-import cn.dev33.satoken.dao.SaTokenDao;
-import cn.dev33.satoken.util.SaFoxUtil;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import org.springframework.stereotype.Component;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Sa-Token鎸佷箙灞傛帴鍙�(浣跨敤妗嗘灦鑷甫RedisUtils瀹炵幇 鍗忚缁熶竴)
- *
- * @author Lion Li
- */
-@Component
-public class PlusSaTokenDao implements SaTokenDao {
-
-    /**
-     * 鑾峰彇Value锛屽鏃犺繑绌�
-     */
-    @Override
-    public String get(String key) {
-        return RedisUtils.getCacheObject(key);
-    }
-
-    /**
-     * 鍐欏叆Value锛屽苟璁惧畾瀛樻椿鏃堕棿 (鍗曚綅: 绉�)
-     */
-    @Override
-    public void set(String key, String value, long timeout) {
-        if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
-            return;
-        }
-        // 鍒ゆ柇鏄惁涓烘案涓嶈繃鏈�
-        if (timeout == SaTokenDao.NEVER_EXPIRE) {
-            RedisUtils.setCacheObject(key, value);
-        } else {
-            RedisUtils.setCacheObject(key, value, Duration.ofSeconds(timeout));
-        }
-    }
-
-    /**
-     * 淇慨鏀规寚瀹歬ey-value閿�煎 (杩囨湡鏃堕棿涓嶅彉)
-     */
-    @Override
-    public void update(String key, String value) {
-        long expire = getTimeout(key);
-        // -2 = 鏃犳閿�
-        if (expire == SaTokenDao.NOT_VALUE_EXPIRE) {
-            return;
-        }
-        this.set(key, value, expire);
-    }
-
-    /**
-     * 鍒犻櫎Value
-     */
-    @Override
-    public void delete(String key) {
-        RedisUtils.deleteObject(key);
-    }
-
-    /**
-     * 鑾峰彇Value鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
-     */
-    @Override
-    public long getTimeout(String key) {
-        long timeout = RedisUtils.getTimeToLive(key);
-        return timeout < 0 ? timeout : timeout / 1000;
-    }
-
-    /**
-     * 淇敼Value鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
-     */
-    @Override
-    public void updateTimeout(String key, long timeout) {
-        // 鍒ゆ柇鏄惁鎯宠璁剧疆涓烘案涔�
-        if (timeout == SaTokenDao.NEVER_EXPIRE) {
-            long expire = getTimeout(key);
-            if (expire == SaTokenDao.NEVER_EXPIRE) {
-                // 濡傛灉鍏跺凡缁忚璁剧疆涓烘案涔咃紝鍒欎笉浣滀换浣曞鐞�
-            } else {
-                // 濡傛灉灏氭湭琚缃负姘镐箙锛岄偅涔堝啀娆et涓�娆�
-                this.set(key, this.get(key), timeout);
-            }
-            return;
-        }
-        RedisUtils.expire(key, Duration.ofSeconds(timeout));
-    }
-
-
-    /**
-     * 鑾峰彇Object锛屽鏃犺繑绌�
-     */
-    @Override
-    public Object getObject(String key) {
-        return RedisUtils.getCacheObject(key);
-    }
-
-    /**
-     * 鍐欏叆Object锛屽苟璁惧畾瀛樻椿鏃堕棿 (鍗曚綅: 绉�)
-     */
-    @Override
-    public void setObject(String key, Object object, long timeout) {
-        if (timeout == 0 || timeout <= SaTokenDao.NOT_VALUE_EXPIRE) {
-            return;
-        }
-        // 鍒ゆ柇鏄惁涓烘案涓嶈繃鏈�
-        if (timeout == SaTokenDao.NEVER_EXPIRE) {
-            RedisUtils.setCacheObject(key, object);
-        } else {
-            RedisUtils.setCacheObject(key, object, Duration.ofSeconds(timeout));
-        }
-    }
-
-    /**
-     * 鏇存柊Object (杩囨湡鏃堕棿涓嶅彉)
-     */
-    @Override
-    public void updateObject(String key, Object object) {
-        long expire = getObjectTimeout(key);
-        // -2 = 鏃犳閿�
-        if (expire == SaTokenDao.NOT_VALUE_EXPIRE) {
-            return;
-        }
-        this.setObject(key, object, expire);
-    }
-
-    /**
-     * 鍒犻櫎Object
-     */
-    @Override
-    public void deleteObject(String key) {
-        RedisUtils.deleteObject(key);
-    }
-
-    /**
-     * 鑾峰彇Object鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
-     */
-    @Override
-    public long getObjectTimeout(String key) {
-        long timeout = RedisUtils.getTimeToLive(key);
-        return timeout < 0 ? timeout : timeout / 1000;
-    }
-
-    /**
-     * 淇敼Object鐨勫墿浣欏瓨娲绘椂闂� (鍗曚綅: 绉�)
-     */
-    @Override
-    public void updateObjectTimeout(String key, long timeout) {
-        // 鍒ゆ柇鏄惁鎯宠璁剧疆涓烘案涔�
-        if (timeout == SaTokenDao.NEVER_EXPIRE) {
-            long expire = getObjectTimeout(key);
-            if (expire == SaTokenDao.NEVER_EXPIRE) {
-                // 濡傛灉鍏跺凡缁忚璁剧疆涓烘案涔咃紝鍒欎笉浣滀换浣曞鐞�
-            } else {
-                // 濡傛灉灏氭湭琚缃负姘镐箙锛岄偅涔堝啀娆et涓�娆�
-                this.setObject(key, this.getObject(key), timeout);
-            }
-            return;
-        }
-        RedisUtils.expire(key, Duration.ofSeconds(timeout));
-    }
-
-
-    /**
-     * 鎼滅储鏁版嵁
-     */
-    @Override
-    public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType) {
-        Collection<String> keys = RedisUtils.keys(prefix + "*" + keyword + "*");
-        List<String> list = new ArrayList<>(keys);
-        return SaFoxUtil.searchList(list, start, size, sortType);
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java
deleted file mode 100644
index 057d183..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.ruoyi.framework.satoken.service;
-
-import cn.dev33.satoken.stp.StpInterface;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.enums.UserType;
-import com.ruoyi.common.helper.LoginHelper;
-import org.springframework.stereotype.Component;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * sa-token 鏉冮檺绠$悊瀹炵幇绫�
- *
- * @author Lion Li
- */
-@Component
-public class SaPermissionImpl implements StpInterface {
-
-    /**
-     * 鑾峰彇鑿滃崟鏉冮檺鍒楄〃
-     */
-    @Override
-    public List<String> getPermissionList(Object loginId, String loginType) {
-        LoginUser loginUser = LoginHelper.getLoginUser();
-        UserType userType = UserType.getUserType(loginUser.getUserType());
-        if (userType == UserType.SYS_USER) {
-            return new ArrayList<>(loginUser.getMenuPermission());
-        } else if (userType == UserType.APP_USER) {
-            // 鍏朵粬绔� 鑷鏍规嵁涓氬姟缂栧啓
-        }
-        return new ArrayList<>();
-    }
-
-    /**
-     * 鑾峰彇瑙掕壊鏉冮檺鍒楄〃
-     */
-    @Override
-    public List<String> getRoleList(Object loginId, String loginType) {
-        LoginUser loginUser = LoginHelper.getLoginUser();
-        UserType userType = UserType.getUserType(loginUser.getUserType());
-        if (userType == UserType.SYS_USER) {
-            return new ArrayList<>(loginUser.getRolePermission());
-        } else if (userType == UserType.APP_USER) {
-            // 鍏朵粬绔� 鑷鏍规嵁涓氬姟缂栧啓
-        }
-        return new ArrayList<>();
-    }
-}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
deleted file mode 100644
index ad68f8f..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.ruoyi.framework.web.exception;
-
-import cn.dev33.satoken.exception.NotLoginException;
-import cn.dev33.satoken.exception.NotPermissionException;
-import cn.dev33.satoken.exception.NotRoleException;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.http.HttpStatus;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.exception.DemoModeException;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StreamUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.mybatis.spring.MyBatisSystemException;
-import org.springframework.context.support.DefaultMessageSourceResolvable;
-import org.springframework.dao.DuplicateKeyException;
-import org.springframework.validation.BindException;
-import org.springframework.web.HttpRequestMethodNotSupportedException;
-import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.validation.ConstraintViolation;
-import jakarta.validation.ConstraintViolationException;
-
-/**
- * 鍏ㄥ眬寮傚父澶勭悊鍣�
- *
- * @author Lion Li
- */
-@Slf4j
-@RestControllerAdvice
-public class GlobalExceptionHandler {
-
-    /**
-     * 鏉冮檺鐮佸紓甯�
-     */
-    @ExceptionHandler(NotPermissionException.class)
-    public R<Void> handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',鏉冮檺鐮佹牎楠屽け璐�'{}'", requestURI, e.getMessage());
-        return R.fail(HttpStatus.HTTP_FORBIDDEN, "娌℃湁璁块棶鏉冮檺锛岃鑱旂郴绠$悊鍛樻巿鏉�");
-    }
-
-    /**
-     * 瑙掕壊鏉冮檺寮傚父
-     */
-    @ExceptionHandler(NotRoleException.class)
-    public R<Void> handleNotRoleException(NotRoleException e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',瑙掕壊鏉冮檺鏍¢獙澶辫触'{}'", requestURI, e.getMessage());
-        return R.fail(HttpStatus.HTTP_FORBIDDEN, "娌℃湁璁块棶鏉冮檺锛岃鑱旂郴绠$悊鍛樻巿鏉�");
-    }
-
-    /**
-     * 璁よ瘉澶辫触
-     */
-    @ExceptionHandler(NotLoginException.class)
-    public R<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',璁よ瘉澶辫触'{}',鏃犳硶璁块棶绯荤粺璧勬簮", requestURI, e.getMessage());
-        return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "璁よ瘉澶辫触锛屾棤娉曡闂郴缁熻祫婧�");
-    }
-
-    /**
-     * 璇锋眰鏂瑰紡涓嶆敮鎸�
-     */
-    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
-    public R<Void> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
-                                                                HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',涓嶆敮鎸�'{}'璇锋眰", requestURI, e.getMethod());
-        return R.fail(e.getMessage());
-    }
-
-    /**
-     * 涓婚敭鎴朥NIQUE绱㈠紩锛屾暟鎹噸澶嶅紓甯�
-     */
-    @ExceptionHandler(DuplicateKeyException.class)
-    public R<Void> handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',鏁版嵁搴撲腑宸插瓨鍦ㄨ褰�'{}'", requestURI, e.getMessage());
-        return R.fail("鏁版嵁搴撲腑宸插瓨鍦ㄨ璁板綍锛岃鑱旂郴绠$悊鍛樼‘璁�");
-    }
-
-    /**
-     * Mybatis绯荤粺寮傚父 閫氱敤澶勭悊
-     */
-    @ExceptionHandler(MyBatisSystemException.class)
-    public R<Void> handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        String message = e.getMessage();
-        if (message.contains("CannotFindDataSourceException")) {
-            log.error("璇锋眰鍦板潃'{}', 鏈壘鍒版暟鎹簮", requestURI);
-            return R.fail("鏈壘鍒版暟鎹簮锛岃鑱旂郴绠$悊鍛樼‘璁�");
-        }
-        log.error("璇锋眰鍦板潃'{}', Mybatis绯荤粺寮傚父", requestURI, e);
-        return R.fail(message);
-    }
-
-    /**
-     * 涓氬姟寮傚父
-     */
-    @ExceptionHandler(ServiceException.class)
-    public R<Void> handleServiceException(ServiceException e, HttpServletRequest request) {
-        log.error(e.getMessage(), e);
-        Integer code = e.getCode();
-        return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage());
-    }
-
-    /**
-     * 鎷︽埅鏈煡鐨勮繍琛屾椂寮傚父
-     */
-    @ExceptionHandler(RuntimeException.class)
-    public R<Void> handleRuntimeException(RuntimeException e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',鍙戠敓鏈煡寮傚父.", requestURI, e);
-        return R.fail(e.getMessage());
-    }
-
-    /**
-     * 绯荤粺寮傚父
-     */
-    @ExceptionHandler(Exception.class)
-    public R<Void> handleException(Exception e, HttpServletRequest request) {
-        String requestURI = request.getRequestURI();
-        log.error("璇锋眰鍦板潃'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
-        return R.fail(e.getMessage());
-    }
-
-    /**
-     * 鑷畾涔夐獙璇佸紓甯�
-     */
-    @ExceptionHandler(BindException.class)
-    public R<Void> handleBindException(BindException e) {
-        log.error(e.getMessage(), e);
-        String message = StreamUtils.join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", ");
-        return R.fail(message);
-    }
-
-    /**
-     * 鑷畾涔夐獙璇佸紓甯�
-     */
-    @ExceptionHandler(ConstraintViolationException.class)
-    public R<Void> constraintViolationException(ConstraintViolationException e) {
-        log.error(e.getMessage(), e);
-        String message = StreamUtils.join(e.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
-        return R.fail(message);
-    }
-
-    /**
-     * 鑷畾涔夐獙璇佸紓甯�
-     */
-    @ExceptionHandler(MethodArgumentNotValidException.class)
-    public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
-        log.error(e.getMessage(), e);
-        String message = e.getBindingResult().getFieldError().getDefaultMessage();
-        return R.fail(message);
-    }
-
-    /**
-     * 婕旂ず妯″紡寮傚父
-     */
-    @ExceptionHandler(DemoModeException.class)
-    public R<Void> handleDemoModeException(DemoModeException e) {
-        return R.fail("婕旂ず妯″紡锛屼笉鍏佽鎿嶄綔");
-    }
-}
diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml
deleted file mode 100644
index 6318c88..0000000
--- a/ruoyi-generator/pom.xml
+++ /dev/null
@@ -1,35 +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>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-generator</artifactId>
-
-    <description>
-        generator浠g爜鐢熸垚
-    </description>
-
-    <dependencies>
-
-        <!--velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
-        <dependency>
-            <groupId>org.apache.velocity</groupId>
-            <artifactId>velocity-engine-core</artifactId>
-        </dependency>
-
-        <!-- 閫氱敤宸ュ叿-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
deleted file mode 100644
index b162c1f..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package com.ruoyi.generator.controller;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.io.IoUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.generator.domain.GenTable;
-import com.ruoyi.generator.domain.GenTableColumn;
-import com.ruoyi.generator.service.IGenTableService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/tool/gen")
-public class GenController extends BaseController {
-
-    private final IGenTableService genTableService;
-
-    /**
-     * 鏌ヨ浠g爜鐢熸垚鍒楄〃
-     */
-    @SaCheckPermission("tool:gen:list")
-    @GetMapping("/list")
-    public TableDataInfo<GenTable> genList(GenTable genTable, PageQuery pageQuery) {
-        return genTableService.selectPageGenTableList(genTable, pageQuery);
-    }
-
-    /**
-     * 淇敼浠g爜鐢熸垚涓氬姟
-     *
-     * @param tableId 琛↖D
-     */
-    @SaCheckPermission("tool:gen:query")
-    @GetMapping(value = "/{tableId}")
-    public R<Map<String, Object>> getInfo(@PathVariable Long tableId) {
-        GenTable table = genTableService.selectGenTableById(tableId);
-        List<GenTable> tables = genTableService.selectGenTableAll();
-        List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
-        Map<String, Object> map = new HashMap<String, Object>();
-        map.put("info", table);
-        map.put("rows", list);
-        map.put("tables", tables);
-        return R.ok(map);
-    }
-
-    /**
-     * 鏌ヨ鏁版嵁搴撳垪琛�
-     */
-    @SaCheckPermission("tool:gen:list")
-    @GetMapping("/db/list")
-    public TableDataInfo<GenTable> dataList(GenTable genTable, PageQuery pageQuery) {
-        return genTableService.selectPageDbTableList(genTable, pageQuery);
-    }
-
-    /**
-     * 鏌ヨ鏁版嵁琛ㄥ瓧娈靛垪琛�
-     *
-     * @param tableId 琛↖D
-     */
-    @SaCheckPermission("tool:gen:list")
-    @GetMapping(value = "/column/{tableId}")
-    public TableDataInfo<GenTableColumn> columnList(Long tableId) {
-        TableDataInfo<GenTableColumn> dataInfo = new TableDataInfo<>();
-        List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
-        dataInfo.setRows(list);
-        dataInfo.setTotal(list.size());
-        return dataInfo;
-    }
-
-    /**
-     * 瀵煎叆琛ㄧ粨鏋勶紙淇濆瓨锛�
-     *
-     * @param tables 琛ㄥ悕涓�
-     */
-    @SaCheckPermission("tool:gen:import")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.IMPORT)
-    @PostMapping("/importTable")
-    public R<Void> importTableSave(String tables) {
-        String[] tableNames = Convert.toStrArray(tables);
-        // 鏌ヨ琛ㄤ俊鎭�
-        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
-        genTableService.importGenTable(tableList);
-        return R.ok();
-    }
-
-    /**
-     * 淇敼淇濆瓨浠g爜鐢熸垚涓氬姟
-     */
-    @SaCheckPermission("tool:gen:edit")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> editSave(@Validated @RequestBody GenTable genTable) {
-        genTableService.validateEdit(genTable);
-        genTableService.updateGenTable(genTable);
-        return R.ok();
-    }
-
-    /**
-     * 鍒犻櫎浠g爜鐢熸垚
-     *
-     * @param tableIds 琛↖D涓�
-     */
-    @SaCheckPermission("tool:gen:remove")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{tableIds}")
-    public R<Void> remove(@PathVariable Long[] tableIds) {
-        genTableService.deleteGenTableByIds(tableIds);
-        return R.ok();
-    }
-
-    /**
-     * 棰勮浠g爜
-     *
-     * @param tableId 琛↖D
-     */
-    @SaCheckPermission("tool:gen:preview")
-    @GetMapping("/preview/{tableId}")
-    public R<Map<String, String>> preview(@PathVariable("tableId") Long tableId) throws IOException {
-        Map<String, String> dataMap = genTableService.previewCode(tableId);
-        return R.ok(dataMap);
-    }
-
-    /**
-     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
-     *
-     * @param tableName 琛ㄥ悕
-     */
-    @SaCheckPermission("tool:gen:code")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
-    @GetMapping("/download/{tableName}")
-    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException {
-        byte[] data = genTableService.downloadCode(tableName);
-        genCode(response, data);
-    }
-
-    /**
-     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
-     *
-     * @param tableName 琛ㄥ悕
-     */
-    @SaCheckPermission("tool:gen:code")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
-    @GetMapping("/genCode/{tableName}")
-    public R<Void> genCode(@PathVariable("tableName") String tableName) {
-        genTableService.generatorCode(tableName);
-        return R.ok();
-    }
-
-    /**
-     * 鍚屾鏁版嵁搴�
-     *
-     * @param tableName 琛ㄥ悕
-     */
-    @SaCheckPermission("tool:gen:edit")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
-    @GetMapping("/synchDb/{tableName}")
-    public R<Void> synchDb(@PathVariable("tableName") String tableName) {
-        genTableService.synchDb(tableName);
-        return R.ok();
-    }
-
-    /**
-     * 鎵归噺鐢熸垚浠g爜
-     *
-     * @param tables 琛ㄥ悕涓�
-     */
-    @SaCheckPermission("tool:gen:code")
-    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
-    @GetMapping("/batchGenCode")
-    public void batchGenCode(HttpServletResponse response, String tables) throws IOException {
-        String[] tableNames = Convert.toStrArray(tables);
-        byte[] data = genTableService.downloadCode(tableNames);
-        genCode(response, data);
-    }
-
-    /**
-     * 鐢熸垚zip鏂囦欢
-     */
-    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
-        response.reset();
-        response.addHeader("Access-Control-Allow-Origin", "*");
-        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
-        response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
-        response.addHeader("Content-Length", "" + data.length);
-        response.setContentType("application/octet-stream; charset=UTF-8");
-        IoUtil.write(response.getOutputStream(), false, data);
-    }
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
deleted file mode 100644
index 14ff5ae..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package com.ruoyi.generator.domain;
-
-import com.baomidou.mybatisplus.annotation.FieldStrategy;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.constant.GenConstants;
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.utils.StringUtils;
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.apache.commons.lang3.ArrayUtils;
-
-import java.util.List;
-
-/**
- * 涓氬姟琛� gen_table
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("gen_table")
-public class GenTable extends BaseEntity {
-
-    /**
-     * 缂栧彿
-     */
-    @TableId(value = "table_id")
-    private Long tableId;
-
-    /**
-     * 琛ㄥ悕绉�
-     */
-    @NotBlank(message = "琛ㄥ悕绉颁笉鑳戒负绌�")
-    private String tableName;
-
-    /**
-     * 琛ㄦ弿杩�
-     */
-    @NotBlank(message = "琛ㄦ弿杩颁笉鑳戒负绌�")
-    private String tableComment;
-
-    /**
-     * 鍏宠仈鐖惰〃鐨勮〃鍚�
-     */
-    private String subTableName;
-
-    /**
-     * 鏈〃鍏宠仈鐖惰〃鐨勫閿悕
-     */
-    private String subTableFkName;
-
-    /**
-     * 瀹炰綋绫诲悕绉�(棣栧瓧姣嶅ぇ鍐�)
-     */
-    @NotBlank(message = "瀹炰綋绫诲悕绉颁笉鑳戒负绌�")
-    private String className;
-
-    /**
-     * 浣跨敤鐨勬ā鏉匡紙crud鍗曡〃鎿嶄綔 tree鏍戣〃鎿嶄綔 sub涓诲瓙琛ㄦ搷浣滐級
-     */
-    private String tplCategory;
-
-    /**
-     * 鐢熸垚鍖呰矾寰�
-     */
-    @NotBlank(message = "鐢熸垚鍖呰矾寰勪笉鑳戒负绌�")
-    private String packageName;
-
-    /**
-     * 鐢熸垚妯″潡鍚�
-     */
-    @NotBlank(message = "鐢熸垚妯″潡鍚嶄笉鑳戒负绌�")
-    private String moduleName;
-
-    /**
-     * 鐢熸垚涓氬姟鍚�
-     */
-    @NotBlank(message = "鐢熸垚涓氬姟鍚嶄笉鑳戒负绌�")
-    private String businessName;
-
-    /**
-     * 鐢熸垚鍔熻兘鍚�
-     */
-    @NotBlank(message = "鐢熸垚鍔熻兘鍚嶄笉鑳戒负绌�")
-    private String functionName;
-
-    /**
-     * 鐢熸垚浣滆��
-     */
-    @NotBlank(message = "浣滆�呬笉鑳戒负绌�")
-    private String functionAuthor;
-
-    /**
-     * 鐢熸垚浠g爜鏂瑰紡锛�0zip鍘嬬缉鍖� 1鑷畾涔夎矾寰勶級
-     */
-    private String genType;
-
-    /**
-     * 鐢熸垚璺緞锛堜笉濉粯璁ら」鐩矾寰勶級
-     */
-    @TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
-    private String genPath;
-
-    /**
-     * 涓婚敭淇℃伅
-     */
-    @TableField(exist = false)
-    private GenTableColumn pkColumn;
-
-    /**
-     * 琛ㄥ垪淇℃伅
-     */
-    @Valid
-    @TableField(exist = false)
-    private List<GenTableColumn> columns;
-
-    /**
-     * 鍏跺畠鐢熸垚閫夐」
-     */
-    private String options;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 鏍戠紪鐮佸瓧娈�
-     */
-    @TableField(exist = false)
-    private String treeCode;
-
-    /**
-     * 鏍戠埗缂栫爜瀛楁
-     */
-    @TableField(exist = false)
-    private String treeParentCode;
-
-    /**
-     * 鏍戝悕绉板瓧娈�
-     */
-    @TableField(exist = false)
-    private String treeName;
-
-    /*
-     * 鑿滃崟id鍒楄〃
-     */
-    @TableField(exist = false)
-    private List<Long> menuIds;
-
-    /**
-     * 涓婄骇鑿滃崟ID瀛楁
-     */
-    @TableField(exist = false)
-    private String parentMenuId;
-
-    /**
-     * 涓婄骇鑿滃崟鍚嶇О瀛楁
-     */
-    @TableField(exist = false)
-    private String parentMenuName;
-
-    public boolean isTree() {
-        return isTree(this.tplCategory);
-    }
-
-    public static boolean isTree(String tplCategory) {
-        return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
-    }
-
-    public boolean isCrud() {
-        return isCrud(this.tplCategory);
-    }
-
-    public static boolean isCrud(String tplCategory) {
-        return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
-    }
-
-    public boolean isSuperColumn(String javaField) {
-        return isSuperColumn(this.tplCategory, javaField);
-    }
-
-    public static boolean isSuperColumn(String tplCategory, String javaField) {
-        if (isTree(tplCategory)) {
-            return StringUtils.equalsAnyIgnoreCase(javaField,
-                ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
-        }
-        return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
-    }
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
deleted file mode 100644
index d934998..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package com.ruoyi.generator.domain;
-
-import com.baomidou.mybatisplus.annotation.FieldStrategy;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.utils.StringUtils;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.apache.ibatis.type.JdbcType;
-
-import jakarta.validation.constraints.NotBlank;
-
-/**
- * 浠g爜鐢熸垚涓氬姟瀛楁琛� gen_table_column
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("gen_table_column")
-public class GenTableColumn extends BaseEntity {
-
-    /**
-     * 缂栧彿
-     */
-    @TableId(value = "column_id")
-    private Long columnId;
-
-    /**
-     * 褰掑睘琛ㄧ紪鍙�
-     */
-    private Long tableId;
-
-    /**
-     * 鍒楀悕绉�
-     */
-    private String columnName;
-
-    /**
-     * 鍒楁弿杩�
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String columnComment;
-
-    /**
-     * 鍒楃被鍨�
-     */
-    private String columnType;
-
-    /**
-     * JAVA绫诲瀷
-     */
-    private String javaType;
-
-    /**
-     * JAVA瀛楁鍚�
-     */
-    @NotBlank(message = "Java灞炴�т笉鑳戒负绌�")
-    private String javaField;
-
-    /**
-     * 鏄惁涓婚敭锛�1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isPk;
-
-    /**
-     * 鏄惁鑷锛�1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isIncrement;
-
-    /**
-     * 鏄惁蹇呭~锛�1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isRequired;
-
-    /**
-     * 鏄惁涓烘彃鍏ュ瓧娈碉紙1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isInsert;
-
-    /**
-     * 鏄惁缂栬緫瀛楁锛�1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isEdit;
-
-    /**
-     * 鏄惁鍒楄〃瀛楁锛�1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isList;
-
-    /**
-     * 鏄惁鏌ヨ瀛楁锛�1鏄級
-     */
-    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
-    private String isQuery;
-
-    /**
-     * 鏌ヨ鏂瑰紡锛圗Q绛変簬銆丯E涓嶇瓑浜庛�丟T澶т簬銆丩T灏忎簬銆丩IKE妯$硦銆丅ETWEEN鑼冨洿锛�
-     */
-    private String queryType;
-
-    /**
-     * 鏄剧ず绫诲瀷锛坕nput鏂囨湰妗嗐�乼extarea鏂囨湰鍩熴�乻elect涓嬫媺妗嗐�乧heckbox澶嶉�夋銆乺adio鍗曢�夋銆乨atetime鏃ユ湡鎺т欢銆乮mage鍥剧墖涓婁紶鎺т欢銆乽pload鏂囦欢涓婁紶鎺т欢銆乪ditor瀵屾枃鏈帶浠讹級
-     */
-    private String htmlType;
-
-    /**
-     * 瀛楀吀绫诲瀷
-     */
-    private String dictType;
-
-    /**
-     * 鎺掑簭
-     */
-    private Integer sort;
-
-    public String getCapJavaField() {
-        return StringUtils.capitalize(javaField);
-    }
-
-    public boolean isPk() {
-        return isPk(this.isPk);
-    }
-
-    public boolean isPk(String isPk) {
-        return isPk != null && StringUtils.equals("1", isPk);
-    }
-
-    public boolean isIncrement() {
-        return isIncrement(this.isIncrement);
-    }
-
-    public boolean isIncrement(String isIncrement) {
-        return isIncrement != null && StringUtils.equals("1", isIncrement);
-    }
-
-    public boolean isRequired() {
-        return isRequired(this.isRequired);
-    }
-
-    public boolean isRequired(String isRequired) {
-        return isRequired != null && StringUtils.equals("1", isRequired);
-    }
-
-    public boolean isInsert() {
-        return isInsert(this.isInsert);
-    }
-
-    public boolean isInsert(String isInsert) {
-        return isInsert != null && StringUtils.equals("1", isInsert);
-    }
-
-    public boolean isEdit() {
-        return isInsert(this.isEdit);
-    }
-
-    public boolean isEdit(String isEdit) {
-        return isEdit != null && StringUtils.equals("1", isEdit);
-    }
-
-    public boolean isList() {
-        return isList(this.isList);
-    }
-
-    public boolean isList(String isList) {
-        return isList != null && StringUtils.equals("1", isList);
-    }
-
-    public boolean isQuery() {
-        return isQuery(this.isQuery);
-    }
-
-    public boolean isQuery(String isQuery) {
-        return isQuery != null && StringUtils.equals("1", isQuery);
-    }
-
-    public boolean isSuperColumn() {
-        return isSuperColumn(this.javaField);
-    }
-
-    public static boolean isSuperColumn(String javaField) {
-        return StringUtils.equalsAnyIgnoreCase(javaField,
-            // BaseEntity
-            "createBy", "createTime", "updateBy", "updateTime",
-            // TreeEntity
-            "parentName", "parentId");
-    }
-
-    public boolean isUsableColumn() {
-        return isUsableColumn(javaField);
-    }
-
-    public static boolean isUsableColumn(String javaField) {
-        // isSuperColumn()涓殑鍚嶅崟鐢ㄤ簬閬垮厤鐢熸垚澶氫綑Domain灞炴�э紝鑻ユ煇浜涘睘鎬у湪鐢熸垚椤甸潰鏃堕渶瑕佺敤鍒颁笉鑳藉拷鐣ワ紝鍒欐斁鍦ㄦ澶勭櫧鍚嶅崟
-        return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
-    }
-
-    public String readConverterExp() {
-        String remarks = StringUtils.substringBetween(this.columnComment, "锛�", "锛�");
-        StringBuffer sb = new StringBuffer();
-        if (StringUtils.isNotEmpty(remarks)) {
-            for (String value : remarks.split(" ")) {
-                if (StringUtils.isNotEmpty(value)) {
-                    Object startStr = value.subSequence(0, 1);
-                    String endStr = value.substring(1);
-                    sb.append("").append(startStr).append("=").append(endStr).append(",");
-                }
-            }
-            return sb.deleteCharAt(sb.length() - 1).toString();
-        } else {
-            return this.columnComment;
-        }
-    }
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
deleted file mode 100644
index 93578f2..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.generator.mapper;
-
-import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.generator.domain.GenTableColumn;
-
-import java.util.List;
-
-/**
- * 涓氬姟瀛楁 鏁版嵁灞�
- *
- * @author Lion Li
- */
-@InterceptorIgnore(dataPermission = "true")
-public interface GenTableColumnMapper extends BaseMapperPlus<GenTableColumnMapper, GenTableColumn, GenTableColumn> {
-    /**
-     * 鏍规嵁琛ㄥ悕绉版煡璇㈠垪淇℃伅
-     *
-     * @param tableName 琛ㄥ悕绉�
-     * @return 鍒椾俊鎭�
-     */
-    List<GenTableColumn> selectDbTableColumnsByName(String tableName);
-
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
deleted file mode 100644
index f70a11e..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.ruoyi.generator.mapper;
-
-import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.generator.domain.GenTable;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 涓氬姟 鏁版嵁灞�
- *
- * @author Lion Li
- */
-@InterceptorIgnore(dataPermission = "true")
-public interface GenTableMapper extends BaseMapperPlus<GenTableMapper, GenTable, GenTable> {
-
-    /**
-     * 鏌ヨ鎹簱鍒楄〃
-     *
-     * @param genTable 鏌ヨ鏉′欢
-     * @return 鏁版嵁搴撹〃闆嗗悎
-     */
-    Page<GenTable> selectPageDbTableList(@Param("page") Page<GenTable> page, @Param("genTable") GenTable genTable);
-
-    /**
-     * 鏌ヨ鎹簱鍒楄〃
-     *
-     * @param tableNames 琛ㄥ悕绉扮粍
-     * @return 鏁版嵁搴撹〃闆嗗悎
-     */
-    List<GenTable> selectDbTableListByNames(String[] tableNames);
-
-    /**
-     * 鏌ヨ鎵�鏈夎〃淇℃伅
-     *
-     * @return 琛ㄤ俊鎭泦鍚�
-     */
-    List<GenTable> selectGenTableAll();
-
-    /**
-     * 鏌ヨ琛↖D涓氬姟淇℃伅
-     *
-     * @param id 涓氬姟ID
-     * @return 涓氬姟淇℃伅
-     */
-    GenTable selectGenTableById(Long id);
-
-    /**
-     * 鏌ヨ琛ㄥ悕绉颁笟鍔′俊鎭�
-     *
-     * @param tableName 琛ㄥ悕绉�
-     * @return 涓氬姟淇℃伅
-     */
-    GenTable selectGenTableByName(String tableName);
-
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
deleted file mode 100644
index 0836d19..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
+++ /dev/null
@@ -1,461 +0,0 @@
-package com.ruoyi.generator.service;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.lang.Dict;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.constant.GenConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.FileUtils;
-import com.ruoyi.generator.domain.GenTable;
-import com.ruoyi.generator.domain.GenTableColumn;
-import com.ruoyi.generator.mapper.GenTableColumnMapper;
-import com.ruoyi.generator.mapper.GenTableMapper;
-import com.ruoyi.generator.util.GenUtils;
-import com.ruoyi.generator.util.VelocityInitializer;
-import com.ruoyi.generator.util.VelocityUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.Velocity;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.*;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-/**
- * 涓氬姟 鏈嶅姟灞傚疄鐜�
- *
- * @author Lion Li
- */
-@DS("#header.datasource")
-@Slf4j
-@RequiredArgsConstructor
-@Service
-public class GenTableServiceImpl implements IGenTableService {
-
-    private final GenTableMapper baseMapper;
-    private final GenTableColumnMapper genTableColumnMapper;
-    private final IdentifierGenerator identifierGenerator;
-
-    /**
-     * 鏌ヨ涓氬姟瀛楁鍒楄〃
-     *
-     * @param tableId 涓氬姟瀛楁缂栧彿
-     * @return 涓氬姟瀛楁闆嗗悎
-     */
-    @Override
-    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId) {
-        return genTableColumnMapper.selectList(new LambdaQueryWrapper<GenTableColumn>()
-            .eq(GenTableColumn::getTableId, tableId)
-            .orderByAsc(GenTableColumn::getSort));
-    }
-
-    /**
-     * 鏌ヨ涓氬姟淇℃伅
-     *
-     * @param id 涓氬姟ID
-     * @return 涓氬姟淇℃伅
-     */
-    @Override
-    public GenTable selectGenTableById(Long id) {
-        GenTable genTable = baseMapper.selectGenTableById(id);
-        setTableFromOptions(genTable);
-        return genTable;
-    }
-
-    @Override
-    public TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery) {
-        Page<GenTable> page = baseMapper.selectPage(pageQuery.build(), this.buildGenTableQueryWrapper(genTable));
-        return TableDataInfo.build(page);
-    }
-
-    private QueryWrapper<GenTable> buildGenTableQueryWrapper(GenTable genTable) {
-        Map<String, Object> params = genTable.getParams();
-        QueryWrapper<GenTable> wrapper = Wrappers.query();
-        wrapper.like(StringUtils.isNotBlank(genTable.getTableName()), "lower(table_name)", StringUtils.lowerCase(genTable.getTableName()))
-            .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment()))
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                "create_time", params.get("beginTime"), params.get("endTime"));
-        return wrapper;
-    }
-
-
-    @Override
-    public TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery) {
-        Page<GenTable> page = baseMapper.selectPageDbTableList(pageQuery.build(), genTable);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏌ヨ鎹簱鍒楄〃
-     *
-     * @param tableNames 琛ㄥ悕绉扮粍
-     * @return 鏁版嵁搴撹〃闆嗗悎
-     */
-    @Override
-    public List<GenTable> selectDbTableListByNames(String[] tableNames) {
-        return baseMapper.selectDbTableListByNames(tableNames);
-    }
-
-    /**
-     * 鏌ヨ鎵�鏈夎〃淇℃伅
-     *
-     * @return 琛ㄤ俊鎭泦鍚�
-     */
-    @Override
-    public List<GenTable> selectGenTableAll() {
-        return baseMapper.selectGenTableAll();
-    }
-
-    /**
-     * 淇敼涓氬姟
-     *
-     * @param genTable 涓氬姟淇℃伅
-     * @return 缁撴灉
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @Override
-    public void updateGenTable(GenTable genTable) {
-        String options = JsonUtils.toJsonString(genTable.getParams());
-        genTable.setOptions(options);
-        int row = baseMapper.updateById(genTable);
-        if (row > 0) {
-            for (GenTableColumn cenTableColumn : genTable.getColumns()) {
-                genTableColumnMapper.updateById(cenTableColumn);
-            }
-        }
-    }
-
-    /**
-     * 鍒犻櫎涓氬姟瀵硅薄
-     *
-     * @param tableIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
-     * @return 缁撴灉
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @Override
-    public void deleteGenTableByIds(Long[] tableIds) {
-        List<Long> ids = Arrays.asList(tableIds);
-        baseMapper.deleteBatchIds(ids);
-        genTableColumnMapper.delete(new LambdaQueryWrapper<GenTableColumn>().in(GenTableColumn::getTableId, ids));
-    }
-
-    /**
-     * 瀵煎叆琛ㄧ粨鏋�
-     *
-     * @param tableList 瀵煎叆琛ㄥ垪琛�
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @Override
-    public void importGenTable(List<GenTable> tableList) {
-        String operName = LoginHelper.getUsername();
-        try {
-            for (GenTable table : tableList) {
-                String tableName = table.getTableName();
-                GenUtils.initTable(table, operName);
-                int row = baseMapper.insert(table);
-                if (row > 0) {
-                    // 淇濆瓨鍒椾俊鎭�
-                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
-                    List<GenTableColumn> saveColumns = new ArrayList<>();
-                    for (GenTableColumn column : genTableColumns) {
-                        GenUtils.initColumnField(column, table);
-                        saveColumns.add(column);
-                    }
-                    if (CollUtil.isNotEmpty(saveColumns)) {
-                        genTableColumnMapper.insertBatch(saveColumns);
-                    }
-                }
-            }
-        } catch (Exception e) {
-            throw new ServiceException("瀵煎叆澶辫触锛�" + e.getMessage());
-        }
-    }
-
-    /**
-     * 棰勮浠g爜
-     *
-     * @param tableId 琛ㄧ紪鍙�
-     * @return 棰勮鏁版嵁鍒楄〃
-     */
-    @Override
-    public Map<String, String> previewCode(Long tableId) {
-        Map<String, String> dataMap = new LinkedHashMap<>();
-        // 鏌ヨ琛ㄤ俊鎭�
-        GenTable table = baseMapper.selectGenTableById(tableId);
-        List<Long> menuIds = new ArrayList<>();
-        for (int i = 0; i < 6; i++) {
-            menuIds.add(identifierGenerator.nextId(null).longValue());
-        }
-        table.setMenuIds(menuIds);
-        // 璁剧疆涓婚敭鍒椾俊鎭�
-        setPkColumn(table);
-        VelocityInitializer.initVelocity();
-
-        VelocityContext context = VelocityUtils.prepareContext(table);
-
-        // 鑾峰彇妯℃澘鍒楄〃
-        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
-        for (String template : templates) {
-            // 娓叉煋妯℃澘
-            StringWriter sw = new StringWriter();
-            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
-            tpl.merge(context, sw);
-            dataMap.put(template, sw.toString());
-        }
-        return dataMap;
-    }
-
-    /**
-     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
-     *
-     * @param tableName 琛ㄥ悕绉�
-     * @return 鏁版嵁
-     */
-    @Override
-    public byte[] downloadCode(String tableName) {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        ZipOutputStream zip = new ZipOutputStream(outputStream);
-        generatorCode(tableName, zip);
-        IoUtil.close(zip);
-        return outputStream.toByteArray();
-    }
-
-    /**
-     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
-     *
-     * @param tableName 琛ㄥ悕绉�
-     */
-    @Override
-    public void generatorCode(String tableName) {
-        // 鏌ヨ琛ㄤ俊鎭�
-        GenTable table = baseMapper.selectGenTableByName(tableName);
-        // 璁剧疆涓婚敭鍒椾俊鎭�
-        setPkColumn(table);
-
-        VelocityInitializer.initVelocity();
-
-        VelocityContext context = VelocityUtils.prepareContext(table);
-
-        // 鑾峰彇妯℃澘鍒楄〃
-        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
-        for (String template : templates) {
-            if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) {
-                // 娓叉煋妯℃澘
-                StringWriter sw = new StringWriter();
-                Template tpl = Velocity.getTemplate(template, Constants.UTF8);
-                tpl.merge(context, sw);
-                try {
-                    String path = getGenPath(table, template);
-                    FileUtils.writeUtf8String(sw.toString(), path);
-                } catch (Exception e) {
-                    throw new ServiceException("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName());
-                }
-            }
-        }
-    }
-
-    /**
-     * 鍚屾鏁版嵁搴�
-     *
-     * @param tableName 琛ㄥ悕绉�
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @Override
-    public void synchDb(String tableName) {
-        GenTable table = baseMapper.selectGenTableByName(tableName);
-        List<GenTableColumn> tableColumns = table.getColumns();
-        Map<String, GenTableColumn> tableColumnMap = StreamUtils.toIdentityMap(tableColumns, GenTableColumn::getColumnName);
-
-        List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
-        if (CollUtil.isEmpty(dbTableColumns)) {
-            throw new ServiceException("鍚屾鏁版嵁澶辫触锛屽師琛ㄧ粨鏋勪笉瀛樺湪");
-        }
-        List<String> dbTableColumnNames = StreamUtils.toList(dbTableColumns, GenTableColumn::getColumnName);
-
-        List<GenTableColumn> saveColumns = new ArrayList<>();
-        dbTableColumns.forEach(column -> {
-            GenUtils.initColumnField(column, table);
-            if (tableColumnMap.containsKey(column.getColumnName())) {
-                GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
-                column.setColumnId(prevColumn.getColumnId());
-                if (column.isList()) {
-                    // 濡傛灉鏄垪琛紝缁х画淇濈暀鏌ヨ鏂瑰紡/瀛楀吀绫诲瀷閫夐」
-                    column.setDictType(prevColumn.getDictType());
-                    column.setQueryType(prevColumn.getQueryType());
-                }
-                if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
-                    && (column.isInsert() || column.isEdit())
-                    && ((column.isUsableColumn()) || (!column.isSuperColumn()))) {
-                    // 濡傛灉鏄�(鏂板/淇敼&闈炰富閿�/闈炲拷鐣ュ強鐖跺睘鎬�)锛岀户缁繚鐣欏繀濉�/鏄剧ず绫诲瀷閫夐」
-                    column.setIsRequired(prevColumn.getIsRequired());
-                    column.setHtmlType(prevColumn.getHtmlType());
-                }
-                genTableColumnMapper.updateById(column);
-            } else {
-                genTableColumnMapper.insert(column);
-            }
-        });
-        if (CollUtil.isNotEmpty(saveColumns)) {
-            genTableColumnMapper.insertBatch(saveColumns);
-        }
-        List<GenTableColumn> delColumns = StreamUtils.filter(tableColumns, column -> !dbTableColumnNames.contains(column.getColumnName()));
-        if (CollUtil.isNotEmpty(delColumns)) {
-            List<Long> ids = StreamUtils.toList(delColumns, GenTableColumn::getColumnId);
-            genTableColumnMapper.deleteBatchIds(ids);
-        }
-    }
-
-    /**
-     * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
-     *
-     * @param tableNames 琛ㄦ暟缁�
-     * @return 鏁版嵁
-     */
-    @Override
-    public byte[] downloadCode(String[] tableNames) {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        ZipOutputStream zip = new ZipOutputStream(outputStream);
-        for (String tableName : tableNames) {
-            generatorCode(tableName, zip);
-        }
-        IoUtil.close(zip);
-        return outputStream.toByteArray();
-    }
-
-    /**
-     * 鏌ヨ琛ㄤ俊鎭苟鐢熸垚浠g爜
-     */
-    private void generatorCode(String tableName, ZipOutputStream zip) {
-        // 鏌ヨ琛ㄤ俊鎭�
-        GenTable table = baseMapper.selectGenTableByName(tableName);
-        List<Long> menuIds = new ArrayList<>();
-        for (int i = 0; i < 6; i++) {
-            menuIds.add(identifierGenerator.nextId(null).longValue());
-        }
-        table.setMenuIds(menuIds);
-        // 璁剧疆涓婚敭鍒椾俊鎭�
-        setPkColumn(table);
-
-        VelocityInitializer.initVelocity();
-
-        VelocityContext context = VelocityUtils.prepareContext(table);
-
-        // 鑾峰彇妯℃澘鍒楄〃
-        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
-        for (String template : templates) {
-            // 娓叉煋妯℃澘
-            StringWriter sw = new StringWriter();
-            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
-            tpl.merge(context, sw);
-            try {
-                // 娣诲姞鍒皕ip
-                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
-                IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
-                IoUtil.close(sw);
-                zip.flush();
-                zip.closeEntry();
-            } catch (IOException e) {
-                log.error("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName(), e);
-            }
-        }
-    }
-
-    /**
-     * 淇敼淇濆瓨鍙傛暟鏍¢獙
-     *
-     * @param genTable 涓氬姟淇℃伅
-     */
-    @Override
-    public void validateEdit(GenTable genTable) {
-        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
-            String options = JsonUtils.toJsonString(genTable.getParams());
-            Dict paramsObj = JsonUtils.parseMap(options);
-            if (StringUtils.isEmpty(paramsObj.getStr(GenConstants.TREE_CODE))) {
-                throw new ServiceException("鏍戠紪鐮佸瓧娈典笉鑳戒负绌�");
-            } else if (StringUtils.isEmpty(paramsObj.getStr(GenConstants.TREE_PARENT_CODE))) {
-                throw new ServiceException("鏍戠埗缂栫爜瀛楁涓嶈兘涓虹┖");
-            } else if (StringUtils.isEmpty(paramsObj.getStr(GenConstants.TREE_NAME))) {
-                throw new ServiceException("鏍戝悕绉板瓧娈典笉鑳戒负绌�");
-            }
-        }
-    }
-
-    /**
-     * 璁剧疆涓婚敭鍒椾俊鎭�
-     *
-     * @param table 涓氬姟琛ㄤ俊鎭�
-     */
-    public void setPkColumn(GenTable table) {
-        for (GenTableColumn column : table.getColumns()) {
-            if (column.isPk()) {
-                table.setPkColumn(column);
-                break;
-            }
-        }
-        if (ObjectUtil.isNull(table.getPkColumn())) {
-            table.setPkColumn(table.getColumns().get(0));
-        }
-
-    }
-
-    /**
-     * 璁剧疆浠g爜鐢熸垚鍏朵粬閫夐」鍊�
-     *
-     * @param genTable 璁剧疆鍚庣殑鐢熸垚瀵硅薄
-     */
-    public void setTableFromOptions(GenTable genTable) {
-        Dict paramsObj = JsonUtils.parseMap(genTable.getOptions());
-        if (ObjectUtil.isNotNull(paramsObj)) {
-            String treeCode = paramsObj.getStr(GenConstants.TREE_CODE);
-            String treeParentCode = paramsObj.getStr(GenConstants.TREE_PARENT_CODE);
-            String treeName = paramsObj.getStr(GenConstants.TREE_NAME);
-            String parentMenuId = paramsObj.getStr(GenConstants.PARENT_MENU_ID);
-            String parentMenuName = paramsObj.getStr(GenConstants.PARENT_MENU_NAME);
-
-            genTable.setTreeCode(treeCode);
-            genTable.setTreeParentCode(treeParentCode);
-            genTable.setTreeName(treeName);
-            genTable.setParentMenuId(parentMenuId);
-            genTable.setParentMenuName(parentMenuName);
-        }
-    }
-
-    /**
-     * 鑾峰彇浠g爜鐢熸垚鍦板潃
-     *
-     * @param table    涓氬姟琛ㄤ俊鎭�
-     * @param template 妯℃澘鏂囦欢璺緞
-     * @return 鐢熸垚鍦板潃
-     */
-    public static String getGenPath(GenTable table, String template) {
-        String genPath = table.getGenPath();
-        if (StringUtils.equals(genPath, "/")) {
-            return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
-        }
-        return genPath + File.separator + VelocityUtils.getFileName(template, table);
-    }
-}
-
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
deleted file mode 100644
index c432d06..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.ruoyi.generator.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.generator.domain.GenTable;
-import com.ruoyi.generator.domain.GenTableColumn;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 涓氬姟 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface IGenTableService {
-
-    /**
-     * 鏌ヨ涓氬姟瀛楁鍒楄〃
-     *
-     * @param tableId 涓氬姟瀛楁缂栧彿
-     * @return 涓氬姟瀛楁闆嗗悎
-     */
-    List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
-
-    /**
-     * 鏌ヨ涓氬姟鍒楄〃
-     *
-     * @param genTable 涓氬姟淇℃伅
-     * @return 涓氬姟闆嗗悎
-     */
-    TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery);
-
-    /**
-     * 鏌ヨ鎹簱鍒楄〃
-     *
-     * @param genTable 涓氬姟淇℃伅
-     * @return 鏁版嵁搴撹〃闆嗗悎
-     */
-    TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery);
-
-    /**
-     * 鏌ヨ鎹簱鍒楄〃
-     *
-     * @param tableNames 琛ㄥ悕绉扮粍
-     * @return 鏁版嵁搴撹〃闆嗗悎
-     */
-    List<GenTable> selectDbTableListByNames(String[] tableNames);
-
-    /**
-     * 鏌ヨ鎵�鏈夎〃淇℃伅
-     *
-     * @return 琛ㄤ俊鎭泦鍚�
-     */
-    List<GenTable> selectGenTableAll();
-
-    /**
-     * 鏌ヨ涓氬姟淇℃伅
-     *
-     * @param id 涓氬姟ID
-     * @return 涓氬姟淇℃伅
-     */
-    GenTable selectGenTableById(Long id);
-
-    /**
-     * 淇敼涓氬姟
-     *
-     * @param genTable 涓氬姟淇℃伅
-     * @return 缁撴灉
-     */
-    void updateGenTable(GenTable genTable);
-
-    /**
-     * 鍒犻櫎涓氬姟淇℃伅
-     *
-     * @param tableIds 闇�瑕佸垹闄ょ殑琛ㄦ暟鎹甀D
-     * @return 缁撴灉
-     */
-    void deleteGenTableByIds(Long[] tableIds);
-
-    /**
-     * 瀵煎叆琛ㄧ粨鏋�
-     *
-     * @param tableList 瀵煎叆琛ㄥ垪琛�
-     */
-    void importGenTable(List<GenTable> tableList);
-
-    /**
-     * 棰勮浠g爜
-     *
-     * @param tableId 琛ㄧ紪鍙�
-     * @return 棰勮鏁版嵁鍒楄〃
-     */
-    Map<String, String> previewCode(Long tableId);
-
-    /**
-     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
-     *
-     * @param tableName 琛ㄥ悕绉�
-     * @return 鏁版嵁
-     */
-    byte[] downloadCode(String tableName);
-
-    /**
-     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
-     *
-     * @param tableName 琛ㄥ悕绉�
-     * @return 鏁版嵁
-     */
-    void generatorCode(String tableName);
-
-    /**
-     * 鍚屾鏁版嵁搴�
-     *
-     * @param tableName 琛ㄥ悕绉�
-     */
-    void synchDb(String tableName);
-
-    /**
-     * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
-     *
-     * @param tableNames 琛ㄦ暟缁�
-     * @return 鏁版嵁
-     */
-    byte[] downloadCode(String[] tableNames);
-
-    /**
-     * 淇敼淇濆瓨鍙傛暟鏍¢獙
-     *
-     * @param genTable 涓氬姟淇℃伅
-     */
-    void validateEdit(GenTable genTable);
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
deleted file mode 100644
index b6c2248..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
+++ /dev/null
@@ -1,232 +0,0 @@
-package com.ruoyi.generator.util;
-
-import com.ruoyi.common.constant.GenConstants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.generator.config.GenConfig;
-import com.ruoyi.generator.domain.GenTable;
-import com.ruoyi.generator.domain.GenTableColumn;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.commons.lang3.RegExUtils;
-
-import java.util.Arrays;
-
-/**
- * 浠g爜鐢熸垚鍣� 宸ュ叿绫�
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class GenUtils {
-
-    /**
-     * 鍒濆鍖栬〃淇℃伅
-     */
-    public static void initTable(GenTable genTable, String operName) {
-        genTable.setClassName(convertClassName(genTable.getTableName()));
-        genTable.setPackageName(GenConfig.getPackageName());
-        genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
-        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
-        genTable.setFunctionName(replaceText(genTable.getTableComment()));
-        genTable.setFunctionAuthor(GenConfig.getAuthor());
-        genTable.setCreateBy(operName);
-    }
-
-    /**
-     * 鍒濆鍖栧垪灞炴�у瓧娈�
-     */
-    public static void initColumnField(GenTableColumn column, GenTable table) {
-        String dataType = getDbType(column.getColumnType());
-        String columnName = column.getColumnName();
-        column.setTableId(table.getTableId());
-        column.setCreateBy(table.getCreateBy());
-        // 璁剧疆java瀛楁鍚�
-        column.setJavaField(StringUtils.toCamelCase(columnName));
-        // 璁剧疆榛樿绫诲瀷
-        column.setJavaType(GenConstants.TYPE_STRING);
-        column.setQueryType(GenConstants.QUERY_EQ);
-
-        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) {
-            // 瀛楃涓查暱搴﹁秴杩�500璁剧疆涓烘枃鏈煙
-            Integer columnLength = getColumnLength(column.getColumnType());
-            String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
-            column.setHtmlType(htmlType);
-        } else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) {
-            column.setJavaType(GenConstants.TYPE_DATE);
-            column.setHtmlType(GenConstants.HTML_DATETIME);
-        } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
-            column.setHtmlType(GenConstants.HTML_INPUT);
-
-            // 濡傛灉鏄诞鐐瑰瀷 缁熶竴鐢˙igDecimal
-            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
-            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
-                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
-            }
-            // 濡傛灉鏄暣褰�
-            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) {
-                column.setJavaType(GenConstants.TYPE_INTEGER);
-            }
-            // 闀挎暣褰�
-            else {
-                column.setJavaType(GenConstants.TYPE_LONG);
-            }
-        }
-
-        // BO瀵硅薄 榛樿鎻掑叆鍕鹃��
-        if (!arraysContains(GenConstants.COLUMNNAME_NOT_ADD, columnName) && !column.isPk()) {
-            column.setIsInsert(GenConstants.REQUIRE);
-        }
-        // BO瀵硅薄 榛樿缂栬緫鍕鹃��
-        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) {
-            column.setIsEdit(GenConstants.REQUIRE);
-        }
-        // BO瀵硅薄 榛樿鏄惁蹇呭~鍕鹃��
-        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) {
-            column.setIsRequired(GenConstants.REQUIRE);
-        }
-        // VO瀵硅薄 榛樿杩斿洖鍕鹃��
-        if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName)) {
-            column.setIsList(GenConstants.REQUIRE);
-        }
-        // BO瀵硅薄 榛樿鏌ヨ鍕鹃��
-        if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) {
-            column.setIsQuery(GenConstants.REQUIRE);
-        }
-
-        // 鏌ヨ瀛楁绫诲瀷
-        if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
-            column.setQueryType(GenConstants.QUERY_LIKE);
-        }
-        // 鐘舵�佸瓧娈佃缃崟閫夋
-        if (StringUtils.endsWithIgnoreCase(columnName, "status")) {
-            column.setHtmlType(GenConstants.HTML_RADIO);
-        }
-        // 绫诲瀷&鎬у埆瀛楁璁剧疆涓嬫媺妗�
-        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
-            || StringUtils.endsWithIgnoreCase(columnName, "sex")) {
-            column.setHtmlType(GenConstants.HTML_SELECT);
-        }
-        // 鍥剧墖瀛楁璁剧疆鍥剧墖涓婁紶鎺т欢
-        else if (StringUtils.endsWithIgnoreCase(columnName, "image")) {
-            column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
-        }
-        // 鏂囦欢瀛楁璁剧疆鏂囦欢涓婁紶鎺т欢
-        else if (StringUtils.endsWithIgnoreCase(columnName, "file")) {
-            column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
-        }
-        // 鍐呭瀛楁璁剧疆瀵屾枃鏈帶浠�
-        else if (StringUtils.endsWithIgnoreCase(columnName, "content")) {
-            column.setHtmlType(GenConstants.HTML_EDITOR);
-        }
-    }
-
-    /**
-     * 鏍¢獙鏁扮粍鏄惁鍖呭惈鎸囧畾鍊�
-     *
-     * @param arr         鏁扮粍
-     * @param targetValue 鍊�
-     * @return 鏄惁鍖呭惈
-     */
-    public static boolean arraysContains(String[] arr, String targetValue) {
-        return Arrays.asList(arr).contains(targetValue);
-    }
-
-    /**
-     * 鑾峰彇妯″潡鍚�
-     *
-     * @param packageName 鍖呭悕
-     * @return 妯″潡鍚�
-     */
-    public static String getModuleName(String packageName) {
-        int lastIndex = packageName.lastIndexOf(".");
-        int nameLength = packageName.length();
-        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
-    }
-
-    /**
-     * 鑾峰彇涓氬姟鍚�
-     *
-     * @param tableName 琛ㄥ悕
-     * @return 涓氬姟鍚�
-     */
-    public static String getBusinessName(String tableName) {
-        int firstIndex = tableName.indexOf("_");
-        int nameLength = tableName.length();
-        String businessName = StringUtils.substring(tableName, firstIndex + 1, nameLength);
-        businessName = StringUtils.toCamelCase(businessName);
-        return businessName;
-    }
-
-    /**
-     * 琛ㄥ悕杞崲鎴怞ava绫诲悕
-     *
-     * @param tableName 琛ㄥ悕绉�
-     * @return 绫诲悕
-     */
-    public static String convertClassName(String tableName) {
-        boolean autoRemovePre = GenConfig.getAutoRemovePre();
-        String tablePrefix = GenConfig.getTablePrefix();
-        if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) {
-            String[] searchList = StringUtils.split(tablePrefix, ",");
-            tableName = replaceFirst(tableName, searchList);
-        }
-        return StringUtils.convertToCamelCase(tableName);
-    }
-
-    /**
-     * 鎵归噺鏇挎崲鍓嶇紑
-     *
-     * @param replacementm 鏇挎崲鍊�
-     * @param searchList   鏇挎崲鍒楄〃
-     * @return
-     */
-    public static String replaceFirst(String replacementm, String[] searchList) {
-        String text = replacementm;
-        for (String searchString : searchList) {
-            if (replacementm.startsWith(searchString)) {
-                text = replacementm.replaceFirst(searchString, "");
-                break;
-            }
-        }
-        return text;
-    }
-
-    /**
-     * 鍏抽敭瀛楁浛鎹�
-     *
-     * @param text 闇�瑕佽鏇挎崲鐨勫悕瀛�
-     * @return 鏇挎崲鍚庣殑鍚嶅瓧
-     */
-    public static String replaceText(String text) {
-        return RegExUtils.replaceAll(text, "(?:琛▅鑻ヤ緷)", "");
-    }
-
-    /**
-     * 鑾峰彇鏁版嵁搴撶被鍨嬪瓧娈�
-     *
-     * @param columnType 鍒楃被鍨�
-     * @return 鎴彇鍚庣殑鍒楃被鍨�
-     */
-    public static String getDbType(String columnType) {
-        if (StringUtils.indexOf(columnType, '(') > 0) {
-            return StringUtils.substringBefore(columnType, "(");
-        } else {
-            return columnType;
-        }
-    }
-
-    /**
-     * 鑾峰彇瀛楁闀垮害
-     *
-     * @param columnType 鍒楃被鍨�
-     * @return 鎴彇鍚庣殑鍒楃被鍨�
-     */
-    public static Integer getColumnLength(String columnType) {
-        if (StringUtils.indexOf(columnType, '(') > 0) {
-            String length = StringUtils.substringBetween(columnType, "(", ")");
-            return Integer.valueOf(length);
-        } else {
-            return 0;
-        }
-    }
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
deleted file mode 100644
index 67769a8..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.ruoyi.generator.util;
-
-import com.ruoyi.common.constant.Constants;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.velocity.app.Velocity;
-
-import java.util.Properties;
-
-/**
- * VelocityEngine宸ュ巶
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class VelocityInitializer {
-
-    /**
-     * 鍒濆鍖杤m鏂规硶
-     */
-    public static void initVelocity() {
-        Properties p = new Properties();
-        try {
-            // 鍔犺浇classpath鐩綍涓嬬殑vm鏂囦欢
-            p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
-            // 瀹氫箟瀛楃闆�
-            p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
-            // 鍒濆鍖朧elocity寮曟搸锛屾寚瀹氶厤缃甈roperties
-            Velocity.init(p);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
deleted file mode 100644
index e5bb87f..0000000
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
+++ /dev/null
@@ -1,335 +0,0 @@
-package com.ruoyi.generator.util;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.lang.Dict;
-import com.ruoyi.common.constant.GenConstants;
-import com.ruoyi.common.helper.DataBaseHelper;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.generator.domain.GenTable;
-import com.ruoyi.generator.domain.GenTableColumn;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.velocity.VelocityContext;
-
-import java.util.*;
-
-/**
- * 妯℃澘澶勭悊宸ュ叿绫�
- *
- * @author ruoyi
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class VelocityUtils {
-
-    /**
-     * 椤圭洰绌洪棿璺緞
-     */
-    private static final String PROJECT_PATH = "main/java";
-
-    /**
-     * mybatis绌洪棿璺緞
-     */
-    private static final String MYBATIS_PATH = "main/resources/mapper";
-
-    /**
-     * 榛樿涓婄骇鑿滃崟锛岀郴缁熷伐鍏�
-     */
-    private static final String DEFAULT_PARENT_MENU_ID = "3";
-
-    /**
-     * 璁剧疆妯℃澘鍙橀噺淇℃伅
-     *
-     * @return 妯℃澘鍒楄〃
-     */
-    public static VelocityContext prepareContext(GenTable genTable) {
-        String moduleName = genTable.getModuleName();
-        String businessName = genTable.getBusinessName();
-        String packageName = genTable.getPackageName();
-        String tplCategory = genTable.getTplCategory();
-        String functionName = genTable.getFunctionName();
-
-        VelocityContext velocityContext = new VelocityContext();
-        velocityContext.put("tplCategory", genTable.getTplCategory());
-        velocityContext.put("tableName", genTable.getTableName());
-        velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "銆愯濉啓鍔熻兘鍚嶇О銆�");
-        velocityContext.put("ClassName", genTable.getClassName());
-        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
-        velocityContext.put("moduleName", genTable.getModuleName());
-        velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
-        velocityContext.put("businessName", genTable.getBusinessName());
-        velocityContext.put("basePackage", getPackagePrefix(packageName));
-        velocityContext.put("packageName", packageName);
-        velocityContext.put("author", genTable.getFunctionAuthor());
-        velocityContext.put("datetime", DateUtils.getDate());
-        velocityContext.put("pkColumn", genTable.getPkColumn());
-        velocityContext.put("importList", getImportList(genTable));
-        velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
-        velocityContext.put("columns", genTable.getColumns());
-        velocityContext.put("table", genTable);
-        velocityContext.put("dicts", getDicts(genTable));
-        setMenuVelocityContext(velocityContext, genTable);
-        if (GenConstants.TPL_TREE.equals(tplCategory)) {
-            setTreeVelocityContext(velocityContext, genTable);
-        }
-        return velocityContext;
-    }
-
-    public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) {
-        String options = genTable.getOptions();
-        Dict paramsObj = JsonUtils.parseMap(options);
-        String parentMenuId = getParentMenuId(paramsObj);
-        context.put("parentMenuId", parentMenuId);
-    }
-
-    public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) {
-        String options = genTable.getOptions();
-        Dict paramsObj = JsonUtils.parseMap(options);
-        String treeCode = getTreecode(paramsObj);
-        String treeParentCode = getTreeParentCode(paramsObj);
-        String treeName = getTreeName(paramsObj);
-
-        context.put("treeCode", treeCode);
-        context.put("treeParentCode", treeParentCode);
-        context.put("treeName", treeName);
-        context.put("expandColumn", getExpandColumn(genTable));
-        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
-            context.put("tree_parent_code", paramsObj.get(GenConstants.TREE_PARENT_CODE));
-        }
-        if (paramsObj.containsKey(GenConstants.TREE_NAME)) {
-            context.put("tree_name", paramsObj.get(GenConstants.TREE_NAME));
-        }
-    }
-
-    /**
-     * 鑾峰彇妯℃澘淇℃伅
-     *
-     * @return 妯℃澘鍒楄〃
-     */
-    public static List<String> getTemplateList(String tplCategory) {
-        List<String> templates = new ArrayList<String>();
-        templates.add("vm/java/domain.java.vm");
-        templates.add("vm/java/vo.java.vm");
-        templates.add("vm/java/bo.java.vm");
-        templates.add("vm/java/mapper.java.vm");
-        templates.add("vm/java/service.java.vm");
-        templates.add("vm/java/serviceImpl.java.vm");
-        templates.add("vm/java/controller.java.vm");
-        templates.add("vm/xml/mapper.xml.vm");
-        if (DataBaseHelper.isOracle()) {
-            templates.add("vm/sql/oracle/sql.vm");
-        } else if (DataBaseHelper.isPostgerSql()) {
-            templates.add("vm/sql/postgres/sql.vm");
-        } else if (DataBaseHelper.isSqlServer()) {
-            templates.add("vm/sql/sqlserver/sql.vm");
-        } else {
-            templates.add("vm/sql/sql.vm");
-        }
-        templates.add("vm/js/api.js.vm");
-        if (GenConstants.TPL_CRUD.equals(tplCategory)) {
-            templates.add("vm/vue/index.vue.vm");
-        } else if (GenConstants.TPL_TREE.equals(tplCategory)) {
-            templates.add("vm/vue/index-tree.vue.vm");
-        }
-        return templates;
-    }
-
-    /**
-     * 鑾峰彇鏂囦欢鍚�
-     */
-    public static String getFileName(String template, GenTable genTable) {
-        // 鏂囦欢鍚嶇О
-        String fileName = "";
-        // 鍖呰矾寰�
-        String packageName = genTable.getPackageName();
-        // 妯″潡鍚�
-        String moduleName = genTable.getModuleName();
-        // 澶у啓绫诲悕
-        String className = genTable.getClassName();
-        // 涓氬姟鍚嶇О
-        String businessName = genTable.getBusinessName();
-
-        String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
-        String mybatisPath = MYBATIS_PATH + "/" + moduleName;
-        String vuePath = "vue";
-
-        if (template.contains("domain.java.vm")) {
-            fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
-        }
-        if (template.contains("vo.java.vm")) {
-            fileName = StringUtils.format("{}/domain/vo/{}Vo.java", javaPath, className);
-        }
-        if (template.contains("bo.java.vm")) {
-            fileName = StringUtils.format("{}/domain/bo/{}Bo.java", javaPath, className);
-        }
-        if (template.contains("mapper.java.vm")) {
-            fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
-        } else if (template.contains("service.java.vm")) {
-            fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
-        } else if (template.contains("serviceImpl.java.vm")) {
-            fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
-        } else if (template.contains("controller.java.vm")) {
-            fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
-        } else if (template.contains("mapper.xml.vm")) {
-            fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
-        } else if (template.contains("sql.vm")) {
-            fileName = businessName + "Menu.sql";
-        } else if (template.contains("api.js.vm")) {
-            fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
-        } else if (template.contains("index.vue.vm")) {
-            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
-        } else if (template.contains("index-tree.vue.vm")) {
-            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
-        }
-        return fileName;
-    }
-
-    /**
-     * 鑾峰彇鍖呭墠缂�
-     *
-     * @param packageName 鍖呭悕绉�
-     * @return 鍖呭墠缂�鍚嶇О
-     */
-    public static String getPackagePrefix(String packageName) {
-        int lastIndex = packageName.lastIndexOf(".");
-        return StringUtils.substring(packageName, 0, lastIndex);
-    }
-
-    /**
-     * 鏍规嵁鍒楃被鍨嬭幏鍙栧鍏ュ寘
-     *
-     * @param genTable 涓氬姟琛ㄥ璞�
-     * @return 杩斿洖闇�瑕佸鍏ョ殑鍖呭垪琛�
-     */
-    public static HashSet<String> getImportList(GenTable genTable) {
-        List<GenTableColumn> columns = genTable.getColumns();
-        HashSet<String> importList = new HashSet<String>();
-        for (GenTableColumn column : columns) {
-            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) {
-                importList.add("java.util.Date");
-                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
-            } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) {
-                importList.add("java.math.BigDecimal");
-            }
-        }
-        return importList;
-    }
-
-    /**
-     * 鏍规嵁鍒楃被鍨嬭幏鍙栧瓧鍏哥粍
-     *
-     * @param genTable 涓氬姟琛ㄥ璞�
-     * @return 杩斿洖瀛楀吀缁�
-     */
-    public static String getDicts(GenTable genTable) {
-        List<GenTableColumn> columns = genTable.getColumns();
-        Set<String> dicts = new HashSet<String>();
-        addDicts(dicts, columns);
-        return StringUtils.join(dicts, ", ");
-    }
-
-    /**
-     * 娣诲姞瀛楀吀鍒楄〃
-     *
-     * @param dicts 瀛楀吀鍒楄〃
-     * @param columns 鍒楅泦鍚�
-     */
-    public static void addDicts(Set<String> dicts, List<GenTableColumn> columns) {
-        for (GenTableColumn column : columns) {
-            if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
-                column.getHtmlType(),
-                new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) {
-                dicts.add("'" + column.getDictType() + "'");
-            }
-        }
-    }
-
-    /**
-     * 鑾峰彇鏉冮檺鍓嶇紑
-     *
-     * @param moduleName   妯″潡鍚嶇О
-     * @param businessName 涓氬姟鍚嶇О
-     * @return 杩斿洖鏉冮檺鍓嶇紑
-     */
-    public static String getPermissionPrefix(String moduleName, String businessName) {
-        return StringUtils.format("{}:{}", moduleName, businessName);
-    }
-
-    /**
-     * 鑾峰彇涓婄骇鑿滃崟ID瀛楁
-     *
-     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
-     * @return 涓婄骇鑿滃崟ID瀛楁
-     */
-    public static String getParentMenuId(Dict paramsObj) {
-        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
-            && StringUtils.isNotEmpty(paramsObj.getStr(GenConstants.PARENT_MENU_ID))) {
-            return paramsObj.getStr(GenConstants.PARENT_MENU_ID);
-        }
-        return DEFAULT_PARENT_MENU_ID;
-    }
-
-    /**
-     * 鑾峰彇鏍戠紪鐮�
-     *
-     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
-     * @return 鏍戠紪鐮�
-     */
-    public static String getTreecode(Map<String, Object> paramsObj) {
-        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_CODE)) {
-            return StringUtils.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_CODE)));
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 鑾峰彇鏍戠埗缂栫爜
-     *
-     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
-     * @return 鏍戠埗缂栫爜
-     */
-    public static String getTreeParentCode(Dict paramsObj) {
-        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
-            return StringUtils.toCamelCase(paramsObj.getStr(GenConstants.TREE_PARENT_CODE));
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 鑾峰彇鏍戝悕绉�
-     *
-     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
-     * @return 鏍戝悕绉�
-     */
-    public static String getTreeName(Dict paramsObj) {
-        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_NAME)) {
-            return StringUtils.toCamelCase(paramsObj.getStr(GenConstants.TREE_NAME));
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 鑾峰彇闇�瑕佸湪鍝竴鍒椾笂闈㈡樉绀哄睍寮�鎸夐挳
-     *
-     * @param genTable 涓氬姟琛ㄥ璞�
-     * @return 灞曞紑鎸夐挳鍒楀簭鍙�
-     */
-    public static int getExpandColumn(GenTable genTable) {
-        String options = genTable.getOptions();
-        Dict paramsObj = JsonUtils.parseMap(options);
-        String treeName = paramsObj.getStr(GenConstants.TREE_NAME);
-        int num = 0;
-        for (GenTableColumn column : genTable.getColumns()) {
-            if (column.isList()) {
-                num++;
-                String columnName = column.getColumnName();
-                if (columnName.equals(treeName)) {
-                    break;
-                }
-            }
-        }
-        return num;
-    }
-}
diff --git a/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-generator/src/main/resources/generator.yml
deleted file mode 100644
index 4544c8c..0000000
--- a/ruoyi-generator/src/main/resources/generator.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-# 浠g爜鐢熸垚
-gen: 
-  # 浣滆��
-  author: ruoyi
-  # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
-  packageName: com.ruoyi.system
-  # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸false
-  autoRemovePre: false
-  # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
-  tablePrefix: sys_
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
deleted file mode 100644
index 8d6f064..0000000
--- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.generator.mapper.GenTableColumnMapper">
-
-    <resultMap type="com.ruoyi.generator.domain.GenTableColumn" id="GenTableColumnResult">
-    </resultMap>
-
-    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
-            select column_name,
-                   (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required,
-                   (case when column_key = 'PRI' then '1' else '0' end) as is_pk,
-                   ordinal_position as sort,
-                   column_comment,
-                   (case when extra = 'auto_increment' then '1' else '0' end) as is_increment,
-                   column_type
-            from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
-            order by ordinal_position
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
-            select lower(temp.column_name) as column_name,
-                    (case when (temp.nullable = 'N'  and  temp.constraint_type != 'P') then '1' else null end) as is_required,
-                    (case when temp.constraint_type = 'P' then '1' else '0' end) as is_pk,
-                    temp.column_id as sort,
-                    temp.comments as column_comment,
-                    (case when temp.constraint_type = 'P' then '1' else '0' end) as is_increment,
-                    lower(temp.data_type) as column_type
-            from (
-                select col.column_id, col.column_name,col.nullable, col.data_type, colc.comments, uc.constraint_type, row_number()
-                    over (partition by col.column_name order by uc.constraint_type desc) as row_flg
-                from user_tab_columns col
-                left join user_col_comments colc on colc.table_name = col.table_name and colc.column_name = col.column_name
-                left join user_cons_columns ucc on ucc.table_name = col.table_name and ucc.column_name = col.column_name
-                left join user_constraints uc on uc.constraint_name = ucc.constraint_name
-                where col.table_name = upper(#{tableName})
-            ) temp
-            WHERE temp.row_flg = 1
-            ORDER BY temp.column_id
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
-            SELECT column_name, is_required, is_pk, sort, column_comment, is_increment, column_type
-            FROM (
-                SELECT c.relname AS table_name,
-                       a.attname AS column_name,
-                       d.description AS column_comment,
-                       CASE WHEN a.attnotnull AND con.conname IS NULL THEN 1 ELSE 0
-                       END AS is_required,
-                       CASE WHEN con.conname IS NOT NULL THEN 1 ELSE 0
-                       END AS is_pk,
-                       a.attnum AS sort,
-                       CASE WHEN "position"(pg_get_expr(ad.adbin, ad.adrelid),
-                           ((c.relname::text || '_'::text) || a.attname::text) || '_seq'::text) > 0 THEN 1 ELSE 0
-                       END AS is_increment,
-                       btrim(
-                           CASE WHEN t.typelem <![CDATA[ <> ]]> 0::oid AND t.typlen = '-1'::integer THEN 'ARRAY'::text ELSE
-                                CASE WHEN t.typtype = 'd'::"char" THEN format_type(t.typbasetype, NULL::integer)
-                                ELSE format_type(a.atttypid, NULL::integer) END
-                           END, '"'::text
-                       ) AS column_type
-                FROM pg_attribute a
-                    JOIN (pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid) ON a.attrelid = c.oid
-                    LEFT JOIN pg_description d ON d.objoid = c.oid AND a.attnum = d.objsubid
-                    LEFT JOIN pg_constraint con ON con.conrelid = c.oid AND (a.attnum = ANY (con.conkey))
-                    LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
-                    LEFT JOIN pg_type t ON a.atttypid = t.oid
-                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
-                    AND a.attnum > 0
-                    AND n.nspname = 'public'::name
-                ORDER BY c.relname, a.attnum
-            ) temp
-            WHERE table_name = (#{tableName})
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
-            SELECT
-                cast(A.NAME as nvarchar) as column_name,
-                cast(B.NAME as nvarchar) + (case when B.NAME = 'numeric' then '(' + cast(A.prec as nvarchar) + ',' + cast(A.scale as nvarchar) + ')' else '' end) as column_type,
-                cast(G.[VALUE] as nvarchar) as column_comment,
-                (SELECT 1 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE Z WHERE TABLE_NAME = D.NAME and A.NAME = Z.column_name  ) as is_pk,
-                colorder as sort
-            FROM SYSCOLUMNS A
-                LEFT JOIN SYSTYPES B ON A.XTYPE = B.XUSERTYPE
-                INNER JOIN SYSOBJECTS D ON A.ID = D.ID AND D.XTYPE='U' AND D.NAME != 'DTPROPERTIES'
-                LEFT JOIN SYS.EXTENDED_PROPERTIES G ON A.ID = G.MAJOR_ID AND A.COLID = G.MINOR_ID
-                LEFT JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID AND F.MINOR_ID = 0
-            WHERE D.NAME = #{tableName}
-            ORDER BY A.COLORDER
-        </if>
-    </select>
-
-</mapper>
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
deleted file mode 100644
index 4d4e68e..0000000
--- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
+++ /dev/null
@@ -1,220 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
-
-    <!-- 澶氱粨鏋勫祵濂楄嚜鍔ㄦ槧灏勯渶甯︿笂姣忎釜瀹炰綋鐨勪富閿甶d 鍚﹀垯鏄犲皠浼氬け璐� -->
-    <resultMap type="com.ruoyi.generator.domain.GenTable" id="GenTableResult">
-        <id property="tableId" column="table_id" />
-        <collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
-    </resultMap>
-
-    <resultMap type="com.ruoyi.generator.domain.GenTableColumn" id="GenTableColumnResult">
-        <id property="columnId" column="column_id"/>
-    </resultMap>
-
-    <select id="selectPageDbTableList" resultMap="GenTableResult">
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
-            select table_name, table_comment, create_time, update_time
-            from information_schema.tables
-            where table_schema = (select database())
-            AND table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%'
-            AND table_name NOT IN (select table_name from gen_table)
-            <if test="genTable.tableName != null and genTable.tableName != ''">
-                AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%'))
-            </if>
-            <if test="genTable.tableComment != null and genTable.tableComment != ''">
-                AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%'))
-            </if>
-            order by create_time desc
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
-            select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
-            from user_tables dt, user_tab_comments dtc, user_objects uo
-            where dt.table_name = dtc.table_name
-            and dt.table_name = uo.object_name
-            and uo.object_type = 'TABLE'
-            AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
-            AND lower(dt.table_name) NOT IN (select table_name from gen_table)
-            <if test="genTable.tableName != null and genTable.tableName != ''">
-                AND lower(dt.table_name) like lower(concat(concat('%', #{genTable.tableName}), '%'))
-            </if>
-            <if test="genTable.tableComment != null and genTable.tableComment != ''">
-                AND lower(dtc.comments) like lower(concat(concat('%', #{genTable.tableComment}), '%'))
-            </if>
-            order by create_time desc
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
-            select table_name, table_comment, create_time, update_time
-            from (
-                SELECT c.relname AS table_name,
-                        obj_description(c.oid) AS table_comment,
-                        CURRENT_TIMESTAMP AS create_time,
-                        CURRENT_TIMESTAMP AS update_time
-                FROM pg_class c
-                    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
-                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
-                    AND c.relname != 'spatial_%'::text
-                    AND n.nspname = 'public'::name
-                    AND n.nspname <![CDATA[ <> ]]> ''::name
-            ) list_table
-            where table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%'
-            AND table_name NOT IN (select table_name from gen_table)
-            <if test="genTable.tableName != null and genTable.tableName != ''">
-                AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%'))
-            </if>
-            <if test="genTable.tableComment != null and genTable.tableComment != ''">
-                AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%'))
-            </if>
-            order by create_time desc
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
-            SELECT cast(D.NAME as nvarchar) as table_name,
-                   cast(F.VALUE as nvarchar) as table_comment,
-                   crdate as create_time,
-                   refdate as update_time
-            FROM SYSOBJECTS D
-                INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
-                    AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
-                    AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
-                    AND D.NAME NOT IN (select table_name from gen_table)
-            <if test="genTable.tableName != null and genTable.tableName != ''">
-                AND lower(D.NAME) like lower(concat(N'%', N'${genTable.tableName}', N'%'))
-            </if>
-            <if test="genTable.tableComment != null and genTable.tableComment != ''">
-                AND lower(CAST(F.VALUE AS nvarchar)) like lower(concat(N'%', N'${genTable.tableComment}', N'%'))
-            </if>
-            order by crdate desc
-        </if>
-    </select>
-
-    <select id="selectDbTableListByNames" resultMap="GenTableResult">
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
-            select table_name, table_comment, create_time, update_time from information_schema.tables
-            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
-            and table_name in
-            <foreach collection="array" item="name" open="(" separator="," close=")">
-                 #{name}
-            </foreach>
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
-            select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
-            from user_tables dt, user_tab_comments dtc, user_objects uo
-            where dt.table_name = dtc.table_name
-            and dt.table_name = uo.object_name
-            and uo.object_type = 'TABLE'
-            AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
-            AND dt.table_name NOT IN (select table_name from gen_table)
-            and lower(dt.table_name) in
-            <foreach collection="array" item="name" open="(" separator="," close=")">
-                #{name}
-            </foreach>
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
-            select table_name, table_comment, create_time, update_time
-            from (
-                SELECT c.relname AS table_name,
-                        obj_description(c.oid) AS table_comment,
-                        CURRENT_TIMESTAMP AS create_time,
-                        CURRENT_TIMESTAMP AS update_time
-                FROM pg_class c
-                    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
-                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
-                    AND c.relname != 'spatial_%'::text
-                    AND n.nspname = 'public'::name
-                    AND n.nspname <![CDATA[ <> ]]> ''::name
-            ) list_table
-            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%'
-            and table_name in
-            <foreach collection="array" item="name" open="(" separator="," close=")">
-                #{name}
-            </foreach>
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
-            SELECT cast(D.NAME as nvarchar) as table_name,
-                   cast(F.VALUE as nvarchar) as table_comment,
-                   crdate as create_time,
-                   refdate as update_time
-            FROM SYSOBJECTS D
-                INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
-                    AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
-                    AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
-                    AND D.NAME in
-            <foreach collection="array" item="name" open="(" separator="," close=")">
-                #{name}
-            </foreach>
-        </if>
-    </select>
-
-    <select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
-            select table_name, table_comment, create_time, update_time from information_schema.tables
-            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
-            and table_name = #{tableName}
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
-            select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
-            from user_tables dt, user_tab_comments dtc, user_objects uo
-            where dt.table_name = dtc.table_name
-            and dt.table_name = uo.object_name
-            and uo.object_type = 'TABLE'
-            AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
-            AND dt.table_name NOT IN (select table_name from gen_table)
-            and lower(dt.table_name) = #{tableName}
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
-            select table_name, table_comment, create_time, update_time
-            from (
-                SELECT c.relname AS table_name,
-                        obj_description(c.oid) AS table_comment,
-                        CURRENT_TIMESTAMP AS create_time,
-                        CURRENT_TIMESTAMP AS update_time
-                FROM pg_class c
-                    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
-                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
-                    AND c.relname != 'spatial_%'::text
-                    AND n.nspname = 'public'::name
-                    AND n.nspname <![CDATA[ <> ]]> ''::name
-            ) list_table
-            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%'
-            and table_name = #{tableName}
-        </if>
-        <if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
-            SELECT cast(D.NAME as nvarchar) as table_name,
-                   cast(F.VALUE as nvarchar) as table_comment,
-                   crdate as create_time,
-                   refdate as update_time
-            FROM SYSOBJECTS D
-                INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
-                    AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
-                    AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
-                    AND D.NAME = #{tableName}
-        </if>
-    </select>
-
-    <select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
-        SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
-               c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
-        FROM gen_table t
-             LEFT JOIN gen_table_column c ON t.table_id = c.table_id
-        where t.table_id = #{tableId} order by c.sort
-    </select>
-
-    <select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
-        SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
-               c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
-        FROM gen_table t
-             LEFT JOIN gen_table_column c ON t.table_id = c.table_id
-        where t.table_name = #{tableName} order by c.sort
-    </select>
-
-    <select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
-        SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
-               c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
-        FROM gen_table t
-             LEFT JOIN gen_table_column c ON t.table_id = c.table_id
-        order by c.sort
-    </select>
-
-</mapper>
diff --git a/ruoyi-generator/src/main/resources/vm/java/bo.java.vm b/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
deleted file mode 100644
index f9f7c20..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
+++ /dev/null
@@ -1,60 +0,0 @@
-package ${packageName}.domain.bo;
-
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import jakarta.validation.constraints.*;
-
-import java.util.Date;
-
-#foreach ($import in $importList)
-import ${import};
-#end
-#if($table.crud || $table.sub)
-import com.ruoyi.common.core.domain.BaseEntity;
-#elseif($table.tree)
-import com.ruoyi.common.core.domain.TreeEntity;
-#end
-
-/**
- * ${functionName}涓氬姟瀵硅薄 ${tableName}
- *
- * @author ${author}
- * @date ${datetime}
- */
-#if($table.crud || $table.sub)
-#set($Entity="BaseEntity")
-#elseif($table.tree)
-#set($Entity="TreeEntity<${ClassName}Bo>")
-#end
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class ${ClassName}Bo extends ${Entity} {
-
-#foreach ($column in $columns)
-#if(!$table.isSuperColumn($column.javaField) && ($column.query || $column.isInsert || $column.isEdit))
-    /**
-     * $column.columnComment
-     */
-#if($column.isInsert && $column.isEdit)
-#set($Group="AddGroup.class, EditGroup.class")
-#elseif($column.isInsert)
-#set($Group="AddGroup.class")
-#elseif($column.isEdit)
-#set($Group="EditGroup.class")
-#end
-#if($column.isRequired == 1)
-#if($column.javaType == 'String')
-    @NotBlank(message = "$column.columnComment涓嶈兘涓虹┖", groups = { $Group })
-#else
-    @NotNull(message = "$column.columnComment涓嶈兘涓虹┖", groups = { $Group })
-#end
-#end
-    private $column.javaType $column.javaField;
-
-#end
-#end
-
-}
diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
deleted file mode 100644
index 1c3bace..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
+++ /dev/null
@@ -1,118 +0,0 @@
-package ${packageName}.controller;
-
-import java.util.List;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-
-import lombok.RequiredArgsConstructor;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.constraints.*;
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.validation.annotation.Validated;
-import com.ruoyi.common.annotation.RepeatSubmit;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import com.ruoyi.common.core.validate.QueryGroup;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import ${packageName}.domain.vo.${ClassName}Vo;
-import ${packageName}.domain.bo.${ClassName}Bo;
-import ${packageName}.service.I${ClassName}Service;
-#if($table.crud || $table.sub)
-import com.ruoyi.common.core.page.TableDataInfo;
-#elseif($table.tree)
-#end
-
-/**
- * ${functionName}
- *
- * @author ${author}
- * @date ${datetime}
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/${moduleName}/${businessName}")
-public class ${ClassName}Controller extends BaseController {
-
-    private final I${ClassName}Service i${ClassName}Service;
-
-    /**
-     * 鏌ヨ${functionName}鍒楄〃
-     */
-    @SaCheckPermission("${permissionPrefix}:list")
-    @GetMapping("/list")
-#if($table.crud || $table.sub)
-    public TableDataInfo<${ClassName}Vo> list(${ClassName}Bo bo, PageQuery pageQuery) {
-        return i${ClassName}Service.queryPageList(bo, pageQuery);
-    }
-#elseif($table.tree)
-    public R<List<${ClassName}Vo>> list(${ClassName}Bo bo) {
-        List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
-        return R.ok(list);
-    }
-#end
-
-    /**
-     * 瀵煎嚭${functionName}鍒楄〃
-     */
-    @SaCheckPermission("${permissionPrefix}:export")
-    @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
-    @PostMapping("/export")
-    public void export(${ClassName}Bo bo, HttpServletResponse response) {
-        List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
-        ExcelUtil.exportExcel(list, "${functionName}", ${ClassName}Vo.class, response);
-    }
-
-    /**
-     * 鑾峰彇${functionName}璇︾粏淇℃伅
-     *
-     * @param ${pkColumn.javaField} 涓婚敭
-     */
-    @SaCheckPermission("${permissionPrefix}:query")
-    @GetMapping("/{${pkColumn.javaField}}")
-    public R<${ClassName}Vo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
-                                     @PathVariable ${pkColumn.javaType} ${pkColumn.javaField}) {
-        return R.ok(i${ClassName}Service.queryById(${pkColumn.javaField}));
-    }
-
-    /**
-     * 鏂板${functionName}
-     */
-    @SaCheckPermission("${permissionPrefix}:add")
-    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
-    @RepeatSubmit()
-    @PostMapping()
-    public R<Void> add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
-        return toAjax(i${ClassName}Service.insertByBo(bo));
-    }
-
-    /**
-     * 淇敼${functionName}
-     */
-    @SaCheckPermission("${permissionPrefix}:edit")
-    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
-    @RepeatSubmit()
-    @PutMapping()
-    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
-        return toAjax(i${ClassName}Service.updateByBo(bo));
-    }
-
-    /**
-     * 鍒犻櫎${functionName}
-     *
-     * @param ${pkColumn.javaField}s 涓婚敭涓�
-     */
-    @SaCheckPermission("${permissionPrefix}:remove")
-    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{${pkColumn.javaField}s}")
-    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
-                          @PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
-        return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true));
-    }
-}
diff --git a/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
deleted file mode 100644
index 1fdc913..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
+++ /dev/null
@@ -1,57 +0,0 @@
-package ${packageName}.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-import java.math.BigDecimal;
-
-#foreach ($import in $importList)
-import ${import};
-#end
-#if($table.crud || $table.sub)
-import com.ruoyi.common.core.domain.BaseEntity;
-#elseif($table.tree)
-import com.ruoyi.common.core.domain.TreeEntity;
-#end
-
-/**
- * ${functionName}瀵硅薄 ${tableName}
- *
- * @author ${author}
- * @date ${datetime}
- */
-#if($table.crud || $table.sub)
-    #set($Entity="BaseEntity")
-#elseif($table.tree)
-    #set($Entity="TreeEntity<${ClassName}>")
-#end
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("${tableName}")
-public class ${ClassName} extends ${Entity} {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-#foreach ($column in $columns)
-#if(!$table.isSuperColumn($column.javaField))
-    /**
-     * $column.columnComment
-     */
-#if($column.javaField=='delFlag')
-    @TableLogic
-#end
-#if($column.javaField=='version')
-    @Version
-#end
-#if($column.isPk==1)
-    @TableId(value = "$column.columnName")
-#end
-    private $column.javaType $column.javaField;
-#end
-#end
-
-}
diff --git a/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
deleted file mode 100644
index 37e7345..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
+++ /dev/null
@@ -1,15 +0,0 @@
-package ${packageName}.mapper;
-
-import ${packageName}.domain.${ClassName};
-import ${packageName}.domain.vo.${ClassName}Vo;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-
-/**
- * ${functionName}Mapper鎺ュ彛
- *
- * @author ${author}
- * @date ${datetime}
- */
-public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}Mapper, ${ClassName}, ${ClassName}Vo> {
-
-}
diff --git a/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
deleted file mode 100644
index 7faafb8..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/service.java.vm
+++ /dev/null
@@ -1,53 +0,0 @@
-package ${packageName}.service;
-
-import ${packageName}.domain.${ClassName};
-import ${packageName}.domain.vo.${ClassName}Vo;
-import ${packageName}.domain.bo.${ClassName}Bo;
-#if($table.crud || $table.sub)
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.domain.PageQuery;
-#end
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * ${functionName}Service鎺ュ彛
- *
- * @author ${author}
- * @date ${datetime}
- */
-public interface I${ClassName}Service {
-
-    /**
-     * 鏌ヨ${functionName}
-     */
-    ${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField});
-
-#if($table.crud || $table.sub)
-    /**
-     * 鏌ヨ${functionName}鍒楄〃
-     */
-    TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery);
-#end
-
-    /**
-     * 鏌ヨ${functionName}鍒楄〃
-     */
-    List<${ClassName}Vo> queryList(${ClassName}Bo bo);
-
-    /**
-     * 鏂板${functionName}
-     */
-    Boolean insertByBo(${ClassName}Bo bo);
-
-    /**
-     * 淇敼${functionName}
-     */
-    Boolean updateByBo(${ClassName}Bo bo);
-
-    /**
-     * 鏍¢獙骞舵壒閲忓垹闄�${functionName}淇℃伅
-     */
-    Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid);
-}
diff --git a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
deleted file mode 100644
index 7767382..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
+++ /dev/null
@@ -1,134 +0,0 @@
-package ${packageName}.service.impl;
-
-import cn.hutool.core.bean.BeanUtil;
-import com.ruoyi.common.utils.StringUtils;
-#if($table.crud || $table.sub)
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-#end
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import ${packageName}.domain.bo.${ClassName}Bo;
-import ${packageName}.domain.vo.${ClassName}Vo;
-import ${packageName}.domain.${ClassName};
-import ${packageName}.mapper.${ClassName}Mapper;
-import ${packageName}.service.I${ClassName}Service;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
-
-/**
- * ${functionName}Service涓氬姟灞傚鐞�
- *
- * @author ${author}
- * @date ${datetime}
- */
-@RequiredArgsConstructor
-@Service
-public class ${ClassName}ServiceImpl implements I${ClassName}Service {
-
-    private final ${ClassName}Mapper baseMapper;
-
-    /**
-     * 鏌ヨ${functionName}
-     */
-    @Override
-    public ${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField}){
-        return baseMapper.selectVoById(${pkColumn.javaField});
-    }
-
-#if($table.crud || $table.sub)
-    /**
-     * 鏌ヨ${functionName}鍒楄〃
-     */
-    @Override
-    public TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
-        Page<${ClassName}Vo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(result);
-    }
-#end
-
-    /**
-     * 鏌ヨ${functionName}鍒楄〃
-     */
-    @Override
-    public List<${ClassName}Vo> queryList(${ClassName}Bo bo) {
-        LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
-        return baseMapper.selectVoList(lqw);
-    }
-
-    private LambdaQueryWrapper<${ClassName}> buildQueryWrapper(${ClassName}Bo bo) {
-        Map<String, Object> params = bo.getParams();
-        LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery();
-#foreach($column in $columns)
-#if($column.query)
-#set($queryType=$column.queryType)
-#set($javaField=$column.javaField)
-#set($javaType=$column.javaType)
-#set($columnName=$column.columnName)
-#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
-#set($mpMethod=$column.queryType.toLowerCase())
-#if($queryType != 'BETWEEN')
-#if($javaType == 'String')
-#set($condition='StringUtils.isNotBlank(bo.get'+$AttrName+'())')
-#else
-#set($condition='bo.get'+$AttrName+'() != null')
-#end
-        lqw.$mpMethod($condition, ${ClassName}::get$AttrName, bo.get$AttrName());
-#else
-        lqw.between(params.get("begin$AttrName") != null && params.get("end$AttrName") != null,
-            ${ClassName}::get$AttrName ,params.get("begin$AttrName"), params.get("end$AttrName"));
-#end
-#end
-#end
-        return lqw;
-    }
-
-    /**
-     * 鏂板${functionName}
-     */
-    @Override
-    public Boolean insertByBo(${ClassName}Bo bo) {
-        ${ClassName} add = BeanUtil.toBean(bo, ${ClassName}.class);
-        validEntityBeforeSave(add);
-        boolean flag = baseMapper.insert(add) > 0;
-#set($pk=$pkColumn.javaField.substring(0,1).toUpperCase() + ${pkColumn.javaField.substring(1)})
-        if (flag) {
-            bo.set$pk(add.get$pk());
-        }
-        return flag;
-    }
-
-    /**
-     * 淇敼${functionName}
-     */
-    @Override
-    public Boolean updateByBo(${ClassName}Bo bo) {
-        ${ClassName} update = BeanUtil.toBean(bo, ${ClassName}.class);
-        validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
-    }
-
-    /**
-     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
-     */
-    private void validEntityBeforeSave(${ClassName} entity){
-        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎${functionName}
-     */
-    @Override
-    public Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid) {
-        if(isValid){
-            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
-        }
-        return baseMapper.deleteBatchIds(ids) > 0;
-    }
-}
diff --git a/ruoyi-generator/src/main/resources/vm/java/vo.java.vm b/ruoyi-generator/src/main/resources/vm/java/vo.java.vm
deleted file mode 100644
index 9c51e59..0000000
--- a/ruoyi-generator/src/main/resources/vm/java/vo.java.vm
+++ /dev/null
@@ -1,56 +0,0 @@
-package ${packageName}.domain.vo;
-
-#foreach ($import in $importList)
-import ${import};
-#end
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import lombok.Data;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-
-
-
-/**
- * ${functionName}瑙嗗浘瀵硅薄 ${tableName}
- *
- * @author ${author}
- * @date ${datetime}
- */
-@Data
-@ExcelIgnoreUnannotated
-public class ${ClassName}Vo implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-#foreach ($column in $columns)
-#if($column.isList)
-    /**
-     * $column.columnComment
-     */
-#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
-#if($parentheseIndex != -1)
-#set($comment=$column.columnComment.substring(0, $parentheseIndex))
-#else
-#set($comment=$column.columnComment)
-#end
-#if(${column.dictType} && ${column.dictType} != '')
-    @ExcelProperty(value = "${comment}", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "${column.dictType}")
-#elseif($parentheseIndex != -1)
-    @ExcelProperty(value = "${comment}", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "$column.readConverterExp()")
-#else
-    @ExcelProperty(value = "${comment}")
-#end
-    private $column.javaType $column.javaField;
-
-#end
-#end
-
-}
diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml
deleted file mode 100644
index 7283bf0..0000000
--- a/ruoyi-job/pom.xml
+++ /dev/null
@@ -1,36 +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>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>jar</packaging>
-    <artifactId>ruoyi-job</artifactId>
-
-    <description>
-        浠诲姟璋冨害
-    </description>
-
-    <dependencies>
-
-        <!-- 閫氱敤宸ュ叿-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-        <!-- xxl-job-core -->
-        <dependency>
-            <groupId>com.xuxueli</groupId>
-            <artifactId>xxl-job-core</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
-
diff --git a/ruoyi-modules/pom.xml b/ruoyi-modules/pom.xml
new file mode 100644
index 0000000..44deef0
--- /dev/null
+++ b/ruoyi-modules/pom.xml
@@ -0,0 +1,27 @@
+<?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>ruoyi-vue-plus</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <modules>
+        <module>ruoyi-demo</module>
+        <module>ruoyi-generator</module>
+        <module>ruoyi-job</module>
+        <module>ruoyi-system</module>
+    </modules>
+
+    <artifactId>ruoyi-modules</artifactId>
+    <packaging>pom</packaging>
+
+    <description>
+        ruoyi-modules 涓氬姟妯″潡
+    </description>
+
+</project>
diff --git a/ruoyi-modules/ruoyi-demo/pom.xml b/ruoyi-modules/ruoyi-demo/pom.xml
new file mode 100644
index 0000000..d0b4301
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/pom.xml
@@ -0,0 +1,75 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-modules</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-demo</artifactId>
+
+    <description>
+        demo妯″潡
+    </description>
+
+    <dependencies>
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-sms</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-idempotent</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-mybatis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-log</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-excel</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-ratelimiter</artifactId>
+        </dependency>
+
+        <!-- 鐭俊 鐢ㄥ摢涓鍏ュ摢涓緷璧� -->
+<!--        <dependency>-->
+<!--            <groupId>com.aliyun</groupId>-->
+<!--            <artifactId>dysmsapi20170525</artifactId>-->
+<!--        </dependency>-->
+
+<!--        <dependency>-->
+<!--            <groupId>com.tencentcloudapi</groupId>-->
+<!--            <artifactId>tencentcloud-sdk-java-sms</artifactId>-->
+<!--        </dependency>-->
+
+    </dependencies>
+
+</project>
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java
new file mode 100644
index 0000000..3d890ac
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java
@@ -0,0 +1,52 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mail.utils.MailUtils;
+import lombok.RequiredArgsConstructor;
+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 java.io.File;
+
+
+/**
+ * 閭欢鍙戦�佹渚�
+ *
+ * @author Michelle.Chung
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/mail")
+public class MailController {
+
+    /**
+     * 鍙戦�侀偖浠�
+     *
+     * @param to      鎺ユ敹浜�
+     * @param subject 鏍囬
+     * @param text    鍐呭
+     */
+    @GetMapping("/sendSimpleMessage")
+    public R<Void> sendSimpleMessage(String to, String subject, String text) {
+        MailUtils.sendText(to, subject, text);
+        return R.ok();
+    }
+
+    /**
+     * 鍙戦�侀偖浠讹紙甯﹂檮浠讹級
+     *
+     * @param to       鎺ユ敹浜�
+     * @param subject  鏍囬
+     * @param text     鍐呭
+     * @param filePath 闄勪欢璺緞
+     */
+    @GetMapping("/sendMessageWithAttachment")
+    public R<Void> sendMessageWithAttachment(String to, String subject, String text, String filePath) {
+        MailUtils.sendText(to, subject, text, new File(filePath));
+        return R.ok();
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java
new file mode 100644
index 0000000..20083ba
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java
@@ -0,0 +1,95 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.Duration;
+
+/**
+ * spring-cache 婕旂ず妗堜緥
+ *
+ * @author Lion Li
+ */
+// 绫荤骇鍒� 缂撳瓨缁熶竴閰嶇疆
+//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE)
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/cache")
+public class RedisCacheController {
+
+    /**
+     * 娴嬭瘯 @Cacheable
+     * <p>
+     * 琛ㄧず杩欎釜鏂规硶鏈変簡缂撳瓨鐨勫姛鑳�,鏂规硶鐨勮繑鍥炲�间細琚紦瀛樹笅鏉�
+     * 涓嬩竴娆¤皟鐢ㄨ鏂规硶鍓�,浼氬幓妫�鏌ユ槸鍚︾紦瀛樹腑宸茬粡鏈夊��
+     * 濡傛灉鏈夊氨鐩存帴杩斿洖,涓嶈皟鐢ㄦ柟娉�
+     * 濡傛灉娌℃湁,灏辫皟鐢ㄦ柟娉�,鐒跺悗鎶婄粨鏋滅紦瀛樿捣鏉�
+     * 杩欎釜娉ㄨВ銆屼竴鑸敤鍦ㄦ煡璇㈡柟娉曚笂銆�
+     * <p>
+     * 閲嶇偣璇存槑: 缂撳瓨娉ㄨВ涓ヨ皑涓庡叾浠栫瓫閫夋暟鎹姛鑳戒竴璧蜂娇鐢�
+     * 渚嬪: 鏁版嵁鏉冮檺娉ㄨВ 浼氶�犳垚 缂撳瓨鍑荤┛ 涓� 鏁版嵁涓嶄竴鑷撮棶棰�
+     * <p>
+     * cacheNames 鍛藉悕瑙勫垯 鏌ョ湅 {@link CacheNames} 娉ㄩ噴 鏀寔澶氬弬鏁�
+     */
+    @Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null")
+    @GetMapping("/test1")
+    public R<String> test1(String key, String value) {
+        return R.ok("鎿嶄綔鎴愬姛", value);
+    }
+
+    /**
+     * 娴嬭瘯 @CachePut
+     * <p>
+     * 鍔犱簡@CachePut娉ㄨВ鐨勬柟娉�,浼氭妸鏂规硶鐨勮繑鍥炲�紁ut鍒扮紦瀛橀噷闈㈢紦瀛樿捣鏉�,渚涘叾瀹冨湴鏂逛娇鐢�
+     * 瀹冦�岄�氬父鐢ㄥ湪鏂板鎴栬�呭疄鏃舵洿鏂版柟娉曚笂銆�
+     * <p>
+     * cacheNames 鍛藉悕瑙勫垯 鏌ョ湅 {@link CacheNames} 娉ㄩ噴 鏀寔澶氬弬鏁�
+     */
+    @CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
+    @GetMapping("/test2")
+    public R<String> test2(String key, String value) {
+        return R.ok("鎿嶄綔鎴愬姛", value);
+    }
+
+    /**
+     * 娴嬭瘯 @CacheEvict
+     * <p>
+     * 浣跨敤浜咰acheEvict娉ㄨВ鐨勬柟娉�,浼氭竻绌烘寚瀹氱紦瀛�
+     * 銆屼竴鑸敤鍦ㄥ垹闄ょ殑鏂规硶涓娿��
+     * <p>
+     * cacheNames 鍛藉悕瑙勫垯 鏌ョ湅 {@link CacheNames} 娉ㄩ噴 鏀寔澶氬弬鏁�
+     */
+    @CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
+    @GetMapping("/test3")
+    public R<String> test3(String key, String value) {
+        return R.ok("鎿嶄綔鎴愬姛", value);
+    }
+
+    /**
+     * 娴嬭瘯璁剧疆杩囨湡鏃堕棿
+     * 鎵嬪姩璁剧疆杩囨湡鏃堕棿10绉�
+     * 11绉掑悗鑾峰彇 鍒ゆ柇鏄惁鐩哥瓑
+     */
+    @GetMapping("/test6")
+    public R<Boolean> test6(String key, String value) {
+        RedisUtils.setCacheObject(key, value);
+        boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10));
+        System.out.println("***********" + flag);
+        try {
+            Thread.sleep(11 * 1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        Object obj = RedisUtils.getCacheObject(key);
+        return R.ok(value.equals(obj));
+    }
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java
new file mode 100644
index 0000000..6ad80ce
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java
@@ -0,0 +1,47 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Redis 鍙戝竷璁㈤槄 婕旂ず妗堜緥
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/redis/pubsub")
+public class RedisPubSubController {
+
+    /**
+     * 鍙戝竷娑堟伅
+     *
+     * @param key   閫氶亾Key
+     * @param value 鍙戦�佸唴瀹�
+     */
+    @GetMapping("/pub")
+    public R<Void> pub(String key, String value) {
+        RedisUtils.publish(key, value, consumer -> {
+            System.out.println("鍙戝竷閫氶亾 => " + key + ", 鍙戦�佸�� => " + value);
+        });
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 璁㈤槄娑堟伅
+     *
+     * @param key 閫氶亾Key
+     */
+    @GetMapping("/sub")
+    public R<Void> sub(String key) {
+        RedisUtils.subscribe(key, String.class, msg -> {
+            System.out.println("璁㈤槄閫氶亾 => " + key + ", 鎺ユ敹鍊� => " + msg);
+        });
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java
new file mode 100644
index 0000000..0fa861f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java
@@ -0,0 +1,52 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.ratelimiter.annotation.RateLimiter;
+import com.ruoyi.common.ratelimiter.enums.LimitType;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * 娴嬭瘯鍒嗗竷寮忛檺娴佹牱渚�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@RestController
+@RequestMapping("/demo/rateLimiter")
+public class RedisRateLimiterController {
+
+    /**
+     * 娴嬭瘯鍏ㄥ眬闄愭祦
+     * 鍏ㄥ眬褰卞搷
+     */
+    @RateLimiter(count = 2, time = 10)
+    @GetMapping("/test")
+    public R<String> test(String value) {
+        return R.ok("鎿嶄綔鎴愬姛", value);
+    }
+
+    /**
+     * 娴嬭瘯璇锋眰IP闄愭祦
+     * 鍚屼竴IP璇锋眰鍙楀奖鍝�
+     */
+    @RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
+    @GetMapping("/testip")
+    public R<String> testip(String value) {
+        return R.ok("鎿嶄綔鎴愬姛", value);
+    }
+
+    /**
+     * 娴嬭瘯闆嗙兢瀹炰緥闄愭祦
+     * 鍚姩涓や釜鍚庣鏈嶅姟浜掍笉褰卞搷
+     */
+    @RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
+    @GetMapping("/testcluster")
+    public R<String> testcluster(String value) {
+        return R.ok("鎿嶄綔鎴愬姛", value);
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java
new file mode 100644
index 0000000..bda9955
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java
@@ -0,0 +1,76 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.sms.config.properties.SmsProperties;
+import com.ruoyi.common.sms.core.SmsTemplate;
+import lombok.RequiredArgsConstructor;
+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 java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鐭俊婕旂ず妗堜緥
+ * 璇峰厛闃呰鏂囨。 鍚﹀垯鏃犳硶浣跨敤
+ *
+ * @author Lion Li
+ * @version 4.2.0
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/sms")
+public class SmsController {
+
+    private final SmsProperties smsProperties;
+//    private final SmsTemplate smsTemplate; // 鍙互浣跨敤spring娉ㄥ叆
+//    private final AliyunSmsTemplate smsTemplate; // 涔熷彲浠ユ敞鍏ユ煇涓巶瀹剁殑妯℃澘宸ュ叿
+
+    /**
+     * 鍙戦�佺煭淇liyun
+     *
+     * @param phones     鐢佃瘽鍙�
+     * @param templateId 妯℃澘ID
+     */
+    @GetMapping("/sendAliyun")
+    public R<Object> sendAliyun(String phones, String templateId) {
+        if (!smsProperties.getEnabled()) {
+            return R.fail("褰撳墠绯荤粺娌℃湁寮�鍚煭淇″姛鑳斤紒");
+        }
+        if (!SpringUtils.containsBean("aliyunSmsTemplate")) {
+            return R.fail("闃块噷浜戜緷璧栨湭寮曞叆锛�");
+        }
+        SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
+        Map<String, String> map = new HashMap<>(1);
+        map.put("code", "1234");
+        Object send = smsTemplate.send(phones, templateId, map);
+        return R.ok(send);
+    }
+
+    /**
+     * 鍙戦�佺煭淇encent
+     *
+     * @param phones     鐢佃瘽鍙�
+     * @param templateId 妯℃澘ID
+     */
+    @GetMapping("/sendTencent")
+    public R<Object> sendTencent(String phones, String templateId) {
+        if (!smsProperties.getEnabled()) {
+            return R.fail("褰撳墠绯荤粺娌℃湁寮�鍚煭淇″姛鑳斤紒");
+        }
+        if (!SpringUtils.containsBean("tencentSmsTemplate")) {
+            return R.fail("鑵捐浜戜緷璧栨湭寮曞叆锛�");
+        }
+        SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
+        Map<String, String> map = new HashMap<>(1);
+//        map.put("2", "娴嬭瘯娴嬭瘯");
+        map.put("1", "1234");
+        Object send = smsTemplate.send(phones, templateId, map);
+        return R.ok(send);
+    }
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
new file mode 100644
index 0000000..84468c6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.demo.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.demo.domain.TestDemo;
+import com.ruoyi.demo.mapper.TestDemoMapper;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 娴嬭瘯鎵归噺鏂规硶
+ *
+ * @author Lion Li
+ * @date 2021-05-30
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/batch")
+public class TestBatchController extends BaseController {
+
+    /**
+     * 涓轰簡渚夸簬娴嬭瘯 鐩存帴寮曞叆mapper
+     */
+    private final TestDemoMapper testDemoMapper;
+
+    /**
+     * 鏂板鎵归噺鏂规硶 鍙畬缇庢浛浠� saveBatch 绉掔骇鎻掑叆涓婁竾鏁版嵁 (瀵筸ysql璐熻嵎杈冨ぇ)
+     * <p>
+     * 3.5.0 鐗堟湰 澧炲姞 rewriteBatchedStatements=true 鎵瑰鐞嗗弬鏁� 浣� MP 鍘熺敓鎵瑰鐞嗗彲浠ヨ揪鍒板悓鏍风殑閫熷害
+     */
+    @PostMapping("/add")
+//    @DS("slave")
+    public R<Void> add() {
+        List<TestDemo> list = new ArrayList<>();
+        for (int i = 0; i < 1000; i++) {
+            TestDemo testDemo = new TestDemo();
+            testDemo.setOrderNum(-1);
+            testDemo.setTestKey("鎵归噺鏂板");
+            testDemo.setValue("娴嬭瘯鏂板");
+            list.add(testDemo);
+        }
+        return toAjax(testDemoMapper.insertBatch(list));
+    }
+
+    /**
+     * 鏂板鎴栨洿鏂� 鍙畬缇庢浛浠� saveOrUpdateBatch 楂樻�ц兘
+     * <p>
+     * 3.5.0 鐗堟湰 澧炲姞 rewriteBatchedStatements=true 鎵瑰鐞嗗弬鏁� 浣� MP 鍘熺敓鎵瑰鐞嗗彲浠ヨ揪鍒板悓鏍风殑閫熷害
+     */
+    @PostMapping("/addOrUpdate")
+//    @DS("slave")
+    public R<Void> addOrUpdate() {
+        List<TestDemo> list = new ArrayList<>();
+        for (int i = 0; i < 1000; i++) {
+            TestDemo testDemo = new TestDemo();
+            testDemo.setOrderNum(-1);
+            testDemo.setTestKey("鎵归噺鏂板");
+            testDemo.setValue("娴嬭瘯鏂板");
+            list.add(testDemo);
+        }
+        testDemoMapper.insertBatch(list);
+        for (int i = 0; i < list.size(); i++) {
+            TestDemo testDemo = list.get(i);
+            testDemo.setTestKey("鎵归噺鏂板鎴栦慨鏀�");
+            testDemo.setValue("鎵归噺鏂板鎴栦慨鏀�");
+            if (i % 2 == 0) {
+                testDemo.setId(null);
+            }
+        }
+        return toAjax(testDemoMapper.insertOrUpdateBatch(list));
+    }
+
+    /**
+     * 鍒犻櫎鎵归噺鏂规硶
+     */
+    @DeleteMapping()
+//    @DS("slave")
+    public R<Void> remove() {
+        return toAjax(testDemoMapper.delete(new LambdaQueryWrapper<TestDemo>()
+            .eq(TestDemo::getOrderNum, -1L)));
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
new file mode 100644
index 0000000..5ff6a07
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
@@ -0,0 +1,148 @@
+package com.ruoyi.demo.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.bean.BeanUtil;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.ValidatorUtils;
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.idempotent.annotation.RepeatSubmit;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.excel.core.ExcelResult;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.demo.domain.TestDemo;
+import com.ruoyi.demo.domain.bo.TestDemoBo;
+import com.ruoyi.demo.domain.bo.TestDemoImportVo;
+import com.ruoyi.demo.domain.vo.TestDemoVo;
+import com.ruoyi.demo.service.ITestDemoService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 娴嬭瘯鍗曡〃Controller
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/demo")
+public class TestDemoController extends BaseController {
+
+    private final ITestDemoService iTestDemoService;
+
+    /**
+     * 鏌ヨ娴嬭瘯鍗曡〃鍒楄〃
+     */
+    @SaCheckPermission("demo:demo:list")
+    @GetMapping("/list")
+    public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
+        return iTestDemoService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 鑷畾涔夊垎椤垫煡璇�
+     */
+    @SaCheckPermission("demo:demo:list")
+    @GetMapping("/page")
+    public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
+        return iTestDemoService.customPageList(bo, pageQuery);
+    }
+
+    /**
+     * 瀵煎叆鏁版嵁
+     *
+     * @param file 瀵煎叆鏂囦欢
+     */
+    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.IMPORT)
+    @SaCheckPermission("demo:demo:import")
+    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception {
+        ExcelResult<TestDemoImportVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true);
+        List<TestDemoImportVo> volist = excelResult.getList();
+        List<TestDemo> list = BeanUtil.copyToList(volist, TestDemo.class);
+        iTestDemoService.saveBatch(list);
+        return R.ok(excelResult.getAnalysis());
+    }
+
+    /**
+     * 瀵煎嚭娴嬭瘯鍗曡〃鍒楄〃
+     */
+    @SaCheckPermission("demo:demo:export")
+    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
+        List<TestDemoVo> list = iTestDemoService.queryList(bo);
+        // 娴嬭瘯闆姳id瀵煎嚭
+//        for (TestDemoVo vo : list) {
+//            vo.setId(1234567891234567893L);
+//        }
+        ExcelUtil.exportExcel(list, "娴嬭瘯鍗曡〃", TestDemoVo.class, response);
+    }
+
+    /**
+     * 鑾峰彇娴嬭瘯鍗曡〃璇︾粏淇℃伅
+     *
+     * @param id 娴嬭瘯ID
+     */
+    @SaCheckPermission("demo:demo:query")
+    @GetMapping("/{id}")
+    public R<TestDemoVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+                                 @PathVariable("id") Long id) {
+        return R.ok(iTestDemoService.queryById(id));
+    }
+
+    /**
+     * 鏂板娴嬭瘯鍗曡〃
+     */
+    @SaCheckPermission("demo:demo:add")
+    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.INSERT)
+    @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}")
+    @PostMapping()
+    public R<Void> add(@RequestBody TestDemoBo bo) {
+        // 浣跨敤鏍¢獙宸ュ叿瀵规爣 @Validated(AddGroup.class) 娉ㄨВ
+        // 鐢ㄤ簬鍦ㄩ潪 Controller 鐨勫湴鏂规牎楠屽璞�
+        ValidatorUtils.validate(bo, AddGroup.class);
+        return toAjax(iTestDemoService.insertByBo(bo));
+    }
+
+    /**
+     * 淇敼娴嬭瘯鍗曡〃
+     */
+    @SaCheckPermission("demo:demo:edit")
+    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.UPDATE)
+    @RepeatSubmit
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) {
+        return toAjax(iTestDemoService.updateByBo(bo));
+    }
+
+    /**
+     * 鍒犻櫎娴嬭瘯鍗曡〃
+     *
+     * @param ids 娴嬭瘯ID涓�
+     */
+    @SaCheckPermission("demo:demo:remove")
+    @Log(title = "娴嬭瘯鍗曡〃", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                          @PathVariable Long[] ids) {
+        return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java
new file mode 100644
index 0000000..8a48dc6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java
@@ -0,0 +1,97 @@
+package com.ruoyi.demo.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 娴嬭瘯Excel鍔熻兘
+ *
+ * @author Lion Li
+ */
+@RestController
+@RequestMapping("/demo/excel")
+public class TestExcelController {
+
+    /**
+     * 鍗曞垪琛ㄥ鏁版嵁
+     */
+    @GetMapping("/exportTemplateOne")
+    public void exportTemplateOne(HttpServletResponse response) {
+        Map<String, String> map = new HashMap<>();
+        map.put("title", "鍗曞垪琛ㄥ鏁版嵁");
+        map.put("test1", "鏁版嵁娴嬭瘯1");
+        map.put("test2", "鏁版嵁娴嬭瘯2");
+        map.put("test3", "鏁版嵁娴嬭瘯3");
+        map.put("test4", "鏁版嵁娴嬭瘯4");
+        map.put("testTest", "666");
+        List<TestObj> list = new ArrayList<>();
+        list.add(new TestObj("鍗曞垪琛ㄦ祴璇�1", "鍒楄〃娴嬭瘯1", "鍒楄〃娴嬭瘯2", "鍒楄〃娴嬭瘯3", "鍒楄〃娴嬭瘯4"));
+        list.add(new TestObj("鍗曞垪琛ㄦ祴璇�2", "鍒楄〃娴嬭瘯5", "鍒楄〃娴嬭瘯6", "鍒楄〃娴嬭瘯7", "鍒楄〃娴嬭瘯8"));
+        list.add(new TestObj("鍗曞垪琛ㄦ祴璇�3", "鍒楄〃娴嬭瘯9", "鍒楄〃娴嬭瘯10", "鍒楄〃娴嬭瘯11", "鍒楄〃娴嬭瘯12"));
+        ExcelUtil.exportTemplate(CollUtil.newArrayList(map, list), "鍗曞垪琛�.xlsx", "excel/鍗曞垪琛�.xlsx", response);
+    }
+
+    /**
+     * 澶氬垪琛ㄥ鏁版嵁
+     */
+    @GetMapping("/exportTemplateMuliti")
+    public void exportTemplateMuliti(HttpServletResponse response) {
+        Map<String, String> map = new HashMap<>();
+        map.put("title1", "鏍囬1");
+        map.put("title2", "鏍囬2");
+        map.put("title3", "鏍囬3");
+        map.put("title4", "鏍囬4");
+        map.put("author", "Lion Li");
+        List<TestObj1> list1 = new ArrayList<>();
+        list1.add(new TestObj1("list1娴嬭瘯1", "list1娴嬭瘯2", "list1娴嬭瘯3"));
+        list1.add(new TestObj1("list1娴嬭瘯4", "list1娴嬭瘯5", "list1娴嬭瘯6"));
+        list1.add(new TestObj1("list1娴嬭瘯7", "list1娴嬭瘯8", "list1娴嬭瘯9"));
+        List<TestObj1> list2 = new ArrayList<>();
+        list2.add(new TestObj1("list2娴嬭瘯1", "list2娴嬭瘯2", "list2娴嬭瘯3"));
+        list2.add(new TestObj1("list2娴嬭瘯4", "list2娴嬭瘯5", "list2娴嬭瘯6"));
+        List<TestObj1> list3 = new ArrayList<>();
+        list3.add(new TestObj1("list3娴嬭瘯1", "list3娴嬭瘯2", "list3娴嬭瘯3"));
+        List<TestObj1> list4 = new ArrayList<>();
+        list4.add(new TestObj1("list4娴嬭瘯1", "list4娴嬭瘯2", "list4娴嬭瘯3"));
+        list4.add(new TestObj1("list4娴嬭瘯4", "list4娴嬭瘯5", "list4娴嬭瘯6"));
+        list4.add(new TestObj1("list4娴嬭瘯7", "list4娴嬭瘯8", "list4娴嬭瘯9"));
+        list4.add(new TestObj1("list4娴嬭瘯10", "list4娴嬭瘯11", "list4娴嬭瘯12"));
+        Map<String, Object> multiListMap = new HashMap<>();
+        multiListMap.put("map", map);
+        multiListMap.put("data1", list1);
+        multiListMap.put("data2", list2);
+        multiListMap.put("data3", list3);
+        multiListMap.put("data4", list4);
+        ExcelUtil.exportTemplateMultiList(multiListMap, "澶氬垪琛�.xlsx", "excel/澶氬垪琛�.xlsx", response);
+    }
+
+    @Data
+    @AllArgsConstructor
+    static class TestObj1 {
+        private String test1;
+        private String test2;
+        private String test3;
+    }
+
+    @Data
+    @AllArgsConstructor
+    static class TestObj {
+        private String name;
+        private String list1;
+        private String list2;
+        private String list3;
+        private String list4;
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java
new file mode 100644
index 0000000..5cc6a2e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java
@@ -0,0 +1,71 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.MessageUtils;
+import lombok.Data;
+import org.hibernate.validator.constraints.Range;
+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 jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+
+/**
+ * 娴嬭瘯鍥介檯鍖�
+ *
+ * @author Lion Li
+ */
+@Validated
+@RestController
+@RequestMapping("/demo/i18n")
+public class TestI18nController {
+
+    /**
+     * 閫氳繃code鑾峰彇鍥介檯鍖栧唴瀹�
+     * code涓� messages.properties 涓殑 key
+     * <p>
+     * 娴嬭瘯浣跨敤 user.register.success
+     *
+     * @param code 鍥介檯鍖朿ode
+     */
+    @GetMapping()
+    public R<Void> get(String code) {
+        return R.ok(MessageUtils.message(code));
+    }
+
+    /**
+     * Validator 鏍¢獙鍥介檯鍖�
+     * 涓嶄紶鍊� 鍒嗗埆鏌ョ湅寮傚父杩斿洖
+     * <p>
+     * 娴嬭瘯浣跨敤 not.null
+     */
+    @GetMapping("/test1")
+    public R<Void> test1(@NotBlank(message = "{not.null}") String str) {
+        return R.ok(str);
+    }
+
+    /**
+     * Bean 鏍¢獙鍥介檯鍖�
+     * 涓嶄紶鍊� 鍒嗗埆鏌ョ湅寮傚父杩斿洖
+     * <p>
+     * 娴嬭瘯浣跨敤 not.null
+     */
+    @GetMapping("/test2")
+    public R<TestI18nBo> test2(@Validated TestI18nBo bo) {
+        return R.ok(bo);
+    }
+
+    @Data
+    public static class TestI18nBo {
+
+        @NotBlank(message = "{not.null}")
+        private String name;
+
+        @NotNull(message = "{not.null}")
+        @Range(min = 0, max = 100, message = "{length.not.valid}")
+        private Integer age;
+    }
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java
new file mode 100644
index 0000000..259c12b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java
@@ -0,0 +1,75 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.annotation.Sensitive;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.enums.SensitiveStrategy;
+import com.ruoyi.common.core.web.controller.BaseController;
+import lombok.Data;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 娴嬭瘯鏁版嵁鑴辨晱鎺у埗鍣�
+ * <p>
+ * 榛樿绠$悊鍛樹笉杩囨护
+ * 闇�鑷鏍规嵁涓氬姟閲嶅啓瀹炵幇
+ *
+ * @author Lion Li
+ * @version 3.6.0
+ * @see com.ruoyi.common.core.service.SensitiveService
+ */
+@RestController
+@RequestMapping("/demo/sensitive")
+public class TestSensitiveController extends BaseController {
+
+    /**
+     * 娴嬭瘯鏁版嵁鑴辨晱
+     */
+    @GetMapping("/test")
+    public R<TestSensitive> test() {
+        TestSensitive testSensitive = new TestSensitive();
+        testSensitive.setIdCard("210397198608215431");
+        testSensitive.setPhone("17640125371");
+        testSensitive.setAddress("鍖椾含甯傛湞闃冲尯鏌愭煇鍥涘悎闄�1203瀹�");
+        testSensitive.setEmail("17640125371@163.com");
+        testSensitive.setBankCard("6226456952351452853");
+        return R.ok(testSensitive);
+    }
+
+    @Data
+    static class TestSensitive {
+
+        /**
+         * 韬唤璇�
+         */
+        @Sensitive(strategy = SensitiveStrategy.ID_CARD)
+        private String idCard;
+
+        /**
+         * 鐢佃瘽
+         */
+        @Sensitive(strategy = SensitiveStrategy.PHONE)
+        private String phone;
+
+        /**
+         * 鍦板潃
+         */
+        @Sensitive(strategy = SensitiveStrategy.ADDRESS)
+        private String address;
+
+        /**
+         * 閭
+         */
+        @Sensitive(strategy = SensitiveStrategy.EMAIL)
+        private String email;
+
+        /**
+         * 閾惰鍗�
+         */
+        @Sensitive(strategy = SensitiveStrategy.BANK_CARD)
+        private String bankCard;
+
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
new file mode 100644
index 0000000..dc080a6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
@@ -0,0 +1,107 @@
+package com.ruoyi.demo.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.common.idempotent.annotation.RepeatSubmit;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.demo.domain.bo.TestTreeBo;
+import com.ruoyi.demo.domain.vo.TestTreeVo;
+import com.ruoyi.demo.service.ITestTreeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 娴嬭瘯鏍戣〃Controller
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/tree")
+public class TestTreeController extends BaseController {
+
+    private final ITestTreeService iTestTreeService;
+
+    /**
+     * 鏌ヨ娴嬭瘯鏍戣〃鍒楄〃
+     */
+    @SaCheckPermission("demo:tree:list")
+    @GetMapping("/list")
+    public R<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) {
+        List<TestTreeVo> list = iTestTreeService.queryList(bo);
+        return R.ok(list);
+    }
+
+    /**
+     * 瀵煎嚭娴嬭瘯鏍戣〃鍒楄〃
+     */
+    @SaCheckPermission("demo:tree:export")
+    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public void export(@Validated TestTreeBo bo, HttpServletResponse response) {
+        List<TestTreeVo> list = iTestTreeService.queryList(bo);
+        ExcelUtil.exportExcel(list, "娴嬭瘯鏍戣〃", TestTreeVo.class, response);
+    }
+
+    /**
+     * 鑾峰彇娴嬭瘯鏍戣〃璇︾粏淇℃伅
+     *
+     * @param id 娴嬭瘯鏍慖D
+     */
+    @SaCheckPermission("demo:tree:query")
+    @GetMapping("/{id}")
+    public R<TestTreeVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+                                 @PathVariable("id") Long id) {
+        return R.ok(iTestTreeService.queryById(id));
+    }
+
+    /**
+     * 鏂板娴嬭瘯鏍戣〃
+     */
+    @SaCheckPermission("demo:tree:add")
+    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.INSERT)
+    @RepeatSubmit
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) {
+        return toAjax(iTestTreeService.insertByBo(bo));
+    }
+
+    /**
+     * 淇敼娴嬭瘯鏍戣〃
+     */
+    @SaCheckPermission("demo:tree:edit")
+    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.UPDATE)
+    @RepeatSubmit
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) {
+        return toAjax(iTestTreeService.updateByBo(bo));
+    }
+
+    /**
+     * 鍒犻櫎娴嬭瘯鏍戣〃
+     *
+     * @param ids 娴嬭瘯鏍慖D涓�
+     */
+    @SaCheckPermission("demo:tree:remove")
+    @Log(title = "娴嬭瘯鏍戣〃", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                          @PathVariable Long[] ids) {
+        return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true));
+    }
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/package-info.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/package-info.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/controller/package-info.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/package-info.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java
new file mode 100644
index 0000000..604a38d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.demo.controller.queue;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.redis.utils.QueueUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 鏈夌晫闃熷垪 婕旂ず妗堜緥
+ * <p>
+ * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
+ * <p>
+ * 闆嗙兢娴嬭瘯閫氳繃 鍚屼竴涓暟鎹彧浼氳娑堣垂涓�娆� 鍋氬ソ浜嬪姟琛ュ伩
+ * 闆嗙兢娴嬭瘯娴佺▼ 鍦ㄥ叾涓竴鍙板彂閫佹暟鎹� 涓ょ鍒嗗埆璋冪敤鑾峰彇鎺ュ彛 涓�娆¤幏鍙栦竴鏉�
+ *
+ * @author Lion Li
+ * @version 3.6.0
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/queue/bounded")
+public class BoundedQueueController {
+
+
+    /**
+     * 娣诲姞闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param capacity  瀹归噺
+     */
+    @GetMapping("/add")
+    public R<Void> add(String queueName, int capacity) {
+        // 鐢ㄥ畬浜嗕竴瀹氳閿�姣� 鍚﹀垯浼氫竴鐩村瓨鍦�
+        boolean b = QueueUtils.destroyQueue(queueName);
+        log.info("閫氶亾: {} , 鍒犻櫎: {}", queueName, b);
+        // 鍒濆鍖栬缃竴娆″嵆鍙�
+        if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) {
+            log.info("閫氶亾: {} , 璁剧疆瀹归噺: {}", queueName, capacity);
+        } else {
+            log.info("閫氶亾: {} , 璁剧疆瀹归噺澶辫触", queueName);
+            return R.fail("鎿嶄綔澶辫触");
+        }
+        for (int i = 0; i < 11; i++) {
+            String data = "data-" + i;
+            boolean flag = QueueUtils.addBoundedQueueObject(queueName, data);
+            if (flag == false) {
+                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {} 澶辫触, 閫氶亾宸叉弧", queueName, data);
+            } else {
+                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}", queueName, data);
+            }
+        }
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 鍒犻櫎闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    @GetMapping("/remove")
+    public R<Void> remove(String queueName) {
+        String data = "data-" + 5;
+        if (QueueUtils.removeQueueObject(queueName, data)) {
+            log.info("閫氶亾: {} , 鍒犻櫎鏁版嵁: {}", queueName, data);
+        } else {
+            return R.fail("鎿嶄綔澶辫触");
+        }
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 鑾峰彇闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    @GetMapping("/get")
+    public R<Void> get(String queueName) {
+        String data;
+        do {
+            data = QueueUtils.getQueueObject(queueName);
+            log.info("閫氶亾: {} , 鑾峰彇鏁版嵁: {}", queueName, data);
+        } while (data != null);
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java
new file mode 100644
index 0000000..3587c2b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.demo.controller.queue;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.redis.utils.QueueUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 寤惰繜闃熷垪 婕旂ず妗堜緥
+ * <p>
+ * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
+ * 渚嬪: 鍒涘缓璁㈠崟30鍒嗛挓鍚庤繃鏈熷鐞�
+ * <p>
+ * 闆嗙兢娴嬭瘯閫氳繃 鍚屼竴涓暟鎹彧浼氳娑堣垂涓�娆� 鍋氬ソ浜嬪姟琛ュ伩
+ * 闆嗙兢娴嬭瘯娴佺▼ 涓ゅ彴闆嗙兢鍒嗗埆寮�鍚闃� 鍦ㄥ叾涓竴鍙板彂閫佹暟鎹� 瑙傚療鎺ユ敹娑堟伅鐨勮寰�
+ *
+ * @author Lion Li
+ * @version 3.6.0
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/queue/delayed")
+public class DelayedQueueController {
+
+    /**
+     * 璁㈤槄闃熷垪
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    @GetMapping("/subscribe")
+    public R<Void> subscribe(String queueName) {
+        log.info("閫氶亾: {} 鐩戝惉涓�......", queueName);
+        // 椤圭洰鍒濆鍖栬缃竴娆″嵆鍙�
+        QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> {
+            // 瑙傚療鎺ユ敹鏃堕棿
+            log.info("閫氶亾: {}, 鏀跺埌鏁版嵁: {}", queueName, orderNum);
+        });
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 娣诲姞闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param orderNum  璁㈠崟鍙�
+     * @param time      寤惰繜鏃堕棿(绉�)
+     */
+    @GetMapping("/add")
+    public R<Void> add(String queueName, String orderNum, Long time) {
+        QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS);
+        // 瑙傚療鍙戦�佹椂闂�
+        log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}", queueName, orderNum);
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 鍒犻櫎闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param orderNum  璁㈠崟鍙�
+     */
+    @GetMapping("/remove")
+    public R<Void> remove(String queueName, String orderNum) {
+        if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) {
+            log.info("閫氶亾: {} , 鍒犻櫎鏁版嵁: {}", queueName, orderNum);
+        } else {
+            return R.fail("鎿嶄綔澶辫触");
+        }
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 閿�姣侀槦鍒�
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    @GetMapping("/destroy")
+    public R<Void> destroy(String queueName) {
+        // 鐢ㄥ畬浜嗕竴瀹氳閿�姣� 鍚﹀垯浼氫竴鐩村瓨鍦�
+        QueueUtils.destroyDelayedQueue(queueName);
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java
new file mode 100644
index 0000000..fcccf14
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java
@@ -0,0 +1,89 @@
+package com.ruoyi.demo.controller.queue;
+
+import cn.hutool.core.util.RandomUtil;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.redis.utils.QueueUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 浼樺厛闃熷垪 婕旂ず妗堜緥
+ * <p>
+ * 杞婚噺绾ч槦鍒� 閲嶉噺绾ф暟鎹噺 璇蜂娇鐢� MQ
+ * <p>
+ * 闆嗙兢娴嬭瘯閫氳繃 鍚屼竴涓秷鎭彧浼氳娑堣垂涓�娆� 鍋氬ソ浜嬪姟琛ュ伩
+ * 闆嗙兢娴嬭瘯娴佺▼ 鍦ㄥ叾涓竴鍙板彂閫佹暟鎹� 涓ょ鍒嗗埆璋冪敤鑾峰彇鎺ュ彛 涓�娆¤幏鍙栦竴鏉�
+ *
+ * @author Lion Li
+ * @version 3.6.0
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/queue/priority")
+public class PriorityQueueController {
+
+    /**
+     * 娣诲姞闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    @GetMapping("/add")
+    public R<Void> add(String queueName) {
+        // 鐢ㄥ畬浜嗕竴瀹氳閿�姣� 鍚﹀垯浼氫竴鐩村瓨鍦�
+        boolean b = QueueUtils.destroyQueue(queueName);
+        log.info("閫氶亾: {} , 鍒犻櫎: {}", queueName, b);
+
+        for (int i = 0; i < 10; i++) {
+            int randomNum = RandomUtil.randomInt(10);
+            PriorityDemo data = new PriorityDemo();
+            data.setName("data-" + i);
+            data.setOrderNum(randomNum);
+            if (QueueUtils.addPriorityQueueObject(queueName, data)) {
+                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}", queueName, data);
+            } else {
+                log.info("閫氶亾: {} , 鍙戦�佹暟鎹�: {}, 鍙戦�佸け璐�", queueName, data);
+            }
+        }
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 鍒犻櫎闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     * @param name      瀵硅薄鍚�
+     * @param orderNum  鎺掑簭鍙�
+     */
+    @GetMapping("/remove")
+    public R<Void> remove(String queueName, String name, Integer orderNum) {
+        PriorityDemo data = new PriorityDemo();
+        data.setName(name);
+        data.setOrderNum(orderNum);
+        if (QueueUtils.removeQueueObject(queueName, data)) {
+            log.info("閫氶亾: {} , 鍒犻櫎鏁版嵁: {}", queueName, data);
+        } else {
+            return R.fail("鎿嶄綔澶辫触");
+        }
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+    /**
+     * 鑾峰彇闃熷垪鏁版嵁
+     *
+     * @param queueName 闃熷垪鍚�
+     */
+    @GetMapping("/get")
+    public R<Void> get(String queueName) {
+        PriorityDemo data;
+        do {
+            data = QueueUtils.getQueueObject(queueName);
+            log.info("閫氶亾: {} , 鑾峰彇鏁版嵁: {}", queueName, data);
+        } while (data != null);
+        return R.ok("鎿嶄綔鎴愬姛");
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java
new file mode 100644
index 0000000..2c3793b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java
@@ -0,0 +1,68 @@
+package com.ruoyi.demo.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 娴嬭瘯鍗曡〃瀵硅薄 test_demo
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("test_demo")
+public class TestDemo extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 閮ㄩ棬id
+     */
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛id
+     */
+    private Long userId;
+
+    /**
+     * 鎺掑簭鍙�
+     */
+    @OrderBy(asc = false, sort = 1)
+    private Integer orderNum;
+
+    /**
+     * key閿�
+     */
+    private String testKey;
+
+    /**
+     * 鍊�
+     */
+    private String value;
+
+    /**
+     * 鐗堟湰
+     */
+    @Version
+    private Long version;
+
+    /**
+     * 鍒犻櫎鏍囧織
+     */
+    @TableLogic
+    private Long delFlag;
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java
new file mode 100644
index 0000000..46f4f67
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java
@@ -0,0 +1,60 @@
+package com.ruoyi.demo.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.Version;
+import com.ruoyi.common.core.web.domain.TreeEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 娴嬭瘯鏍戣〃瀵硅薄 test_tree
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("test_tree")
+public class TestTree extends TreeEntity<TestTree> {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 涓婚敭
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 閮ㄩ棬id
+     */
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛id
+     */
+    private Long userId;
+
+    /**
+     * 鏍戣妭鐐瑰悕
+     */
+    private String treeName;
+
+    /**
+     * 鐗堟湰
+     */
+    @Version
+    private Long version;
+
+    /**
+     * 鍒犻櫎鏍囧織
+     */
+    @TableLogic
+    private Long delFlag;
+
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java
new file mode 100644
index 0000000..5d6bb8c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java
@@ -0,0 +1,59 @@
+package com.ruoyi.demo.domain.bo;
+
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+/**
+ * 娴嬭瘯鍗曡〃涓氬姟瀵硅薄 test_demo
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TestDemoBo extends BaseEntity {
+
+    /**
+     * 涓婚敭
+     */
+    @NotNull(message = "涓婚敭涓嶈兘涓虹┖", groups = {EditGroup.class})
+    private Long id;
+
+    /**
+     * 閮ㄩ棬id
+     */
+    @NotNull(message = "閮ㄩ棬id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛id
+     */
+    @NotNull(message = "鐢ㄦ埛id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    private Long userId;
+
+    /**
+     * 鎺掑簭鍙�
+     */
+    @NotNull(message = "鎺掑簭鍙蜂笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
+    private Integer orderNum;
+
+    /**
+     * key閿�
+     */
+    @NotBlank(message = "key閿笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
+    private String testKey;
+
+    /**
+     * 鍊�
+     */
+    @NotBlank(message = "鍊间笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
+    private String value;
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java
new file mode 100644
index 0000000..b10d42f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java
@@ -0,0 +1,47 @@
+package com.ruoyi.demo.domain.bo;
+
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.web.domain.TreeEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
+/**
+ * 娴嬭瘯鏍戣〃涓氬姟瀵硅薄 test_tree
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TestTreeBo extends TreeEntity<TestTreeBo> {
+
+    /**
+     * 涓婚敭
+     */
+    @NotNull(message = "涓婚敭涓嶈兘涓虹┖", groups = {EditGroup.class})
+    private Long id;
+
+    /**
+     * 閮ㄩ棬id
+     */
+    @NotNull(message = "閮ㄩ棬id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛id
+     */
+    @NotNull(message = "鐢ㄦ埛id涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    private Long userId;
+
+    /**
+     * 鏍戣妭鐐瑰悕
+     */
+    @NotBlank(message = "鏍戣妭鐐瑰悕涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    private String treeName;
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/package-info.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/package-info.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/domain/package-info.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/package-info.java
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
new file mode 100644
index 0000000..f24c994
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
@@ -0,0 +1,58 @@
+package com.ruoyi.demo.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.mybatis.annotation.DataColumn;
+import com.ruoyi.common.mybatis.annotation.DataPermission;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.demo.domain.TestDemo;
+import com.ruoyi.demo.domain.vo.TestDemoVo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 娴嬭瘯鍗曡〃Mapper鎺ュ彛
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+public interface TestDemoMapper extends BaseMapperPlus<TestDemoMapper, TestDemo, TestDemoVo> {
+
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "dept_id"),
+        @DataColumn(key = "userName", value = "user_id")
+    })
+    Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper);
+
+    @Override
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "dept_id"),
+        @DataColumn(key = "userName", value = "user_id")
+    })
+    <P extends IPage<TestDemo>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
+
+    @Override
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "dept_id"),
+        @DataColumn(key = "userName", value = "user_id")
+    })
+    List<TestDemo> selectList(@Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
+
+    @Override
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "dept_id"),
+        @DataColumn(key = "userName", value = "user_id")
+    })
+    int updateById(@Param(Constants.ENTITY) TestDemo entity);
+
+    @Override
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "dept_id"),
+        @DataColumn(key = "userName", value = "user_id")
+    })
+    int deleteBatchIds(@Param(Constants.COLL) Collection<?> idList);
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
new file mode 100644
index 0000000..10c880b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
@@ -0,0 +1,21 @@
+package com.ruoyi.demo.mapper;
+
+import com.ruoyi.common.mybatis.annotation.DataColumn;
+import com.ruoyi.common.mybatis.annotation.DataPermission;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.demo.domain.TestTree;
+import com.ruoyi.demo.domain.vo.TestTreeVo;
+
+/**
+ * 娴嬭瘯鏍戣〃Mapper鎺ュ彛
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+@DataPermission({
+    @DataColumn(key = "deptName", value = "dept_id"),
+    @DataColumn(key = "userName", value = "user_id")
+})
+public interface TestTreeMapper extends BaseMapperPlus<TestTreeMapper, TestTree, TestTreeVo> {
+
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/package-info.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/package-info.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/package-info.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/package-info.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
new file mode 100644
index 0000000..542791d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
@@ -0,0 +1,71 @@
+package com.ruoyi.demo.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.demo.domain.TestDemo;
+import com.ruoyi.demo.domain.bo.TestDemoBo;
+import com.ruoyi.demo.domain.vo.TestDemoVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 娴嬭瘯鍗曡〃Service鎺ュ彛
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+public interface ITestDemoService {
+
+    /**
+     * 鏌ヨ鍗曚釜
+     *
+     * @return
+     */
+    TestDemoVo queryById(Long id);
+
+    /**
+     * 鏌ヨ鍒楄〃
+     */
+    TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery);
+
+    /**
+     * 鑷畾涔夊垎椤垫煡璇�
+     */
+    TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ鍒楄〃
+     */
+    List<TestDemoVo> queryList(TestDemoBo bo);
+
+    /**
+     * 鏍规嵁鏂板涓氬姟瀵硅薄鎻掑叆娴嬭瘯鍗曡〃
+     *
+     * @param bo 娴嬭瘯鍗曡〃鏂板涓氬姟瀵硅薄
+     * @return
+     */
+    Boolean insertByBo(TestDemoBo bo);
+
+    /**
+     * 鏍规嵁缂栬緫涓氬姟瀵硅薄淇敼娴嬭瘯鍗曡〃
+     *
+     * @param bo 娴嬭瘯鍗曡〃缂栬緫涓氬姟瀵硅薄
+     * @return
+     */
+    Boolean updateByBo(TestDemoBo bo);
+
+    /**
+     * 鏍¢獙骞跺垹闄ゆ暟鎹�
+     *
+     * @param ids     涓婚敭闆嗗悎
+     * @param isValid 鏄惁鏍¢獙,true-鍒犻櫎鍓嶆牎楠�,false-涓嶆牎楠�
+     * @return
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 鎵归噺淇濆瓨
+     */
+    Boolean saveBatch(List<TestDemo> list);
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestTreeService.java
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java
new file mode 100644
index 0000000..32ed91c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java
@@ -0,0 +1,110 @@
+package com.ruoyi.demo.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.demo.domain.TestDemo;
+import com.ruoyi.demo.domain.bo.TestDemoBo;
+import com.ruoyi.demo.domain.vo.TestDemoVo;
+import com.ruoyi.demo.mapper.TestDemoMapper;
+import com.ruoyi.demo.service.ITestDemoService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 娴嬭瘯鍗曡〃Service涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+@RequiredArgsConstructor
+@Service
+public class TestDemoServiceImpl implements ITestDemoService {
+
+    private final TestDemoMapper baseMapper;
+
+    @Override
+    public TestDemoVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    @Override
+    public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
+        Page<TestDemoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 鑷畾涔夊垎椤垫煡璇�
+     */
+    @Override
+    public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
+        Page<TestDemoVo> result = baseMapper.customPageList(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    @Override
+    public List<TestDemoVo> queryList(TestDemoBo bo) {
+        return baseMapper.selectVoList(buildQueryWrapper(bo));
+    }
+
+    private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery();
+        lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey());
+        lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue());
+        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
+            TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
+        return lqw;
+    }
+
+    @Override
+    public Boolean insertByBo(TestDemoBo bo) {
+        TestDemo add = BeanUtil.toBean(bo, TestDemo.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    @Override
+    public Boolean updateByBo(TestDemoBo bo) {
+        TestDemo update = BeanUtil.toBean(bo, TestDemo.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+     *
+     * @param entity 瀹炰綋绫绘暟鎹�
+     */
+    private void validEntityBeforeSave(TestDemo entity) {
+        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+        }
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+
+    @Override
+    public Boolean saveBatch(List<TestDemo> list) {
+        return baseMapper.insertBatch(list);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java
new file mode 100644
index 0000000..801a0ea
--- /dev/null
+++ b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java
@@ -0,0 +1,87 @@
+package com.ruoyi.demo.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.demo.domain.TestTree;
+import com.ruoyi.demo.domain.bo.TestTreeBo;
+import com.ruoyi.demo.domain.vo.TestTreeVo;
+import com.ruoyi.demo.mapper.TestTreeMapper;
+import com.ruoyi.demo.service.ITestTreeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 娴嬭瘯鏍戣〃Service涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ * @date 2021-07-26
+ */
+// @DS("slave") // 鍒囨崲浠庡簱鏌ヨ
+@RequiredArgsConstructor
+@Service
+public class TestTreeServiceImpl implements ITestTreeService {
+
+    private final TestTreeMapper baseMapper;
+
+    @Override
+    public TestTreeVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    // @DS("slave") // 鍒囨崲浠庡簱鏌ヨ
+    @Override
+    public List<TestTreeVo> queryList(TestTreeBo bo) {
+        LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery();
+        lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName());
+        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
+            TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
+        return lqw;
+    }
+
+    @Override
+    public Boolean insertByBo(TestTreeBo bo) {
+        TestTree add = BeanUtil.toBean(bo, TestTree.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    @Override
+    public Boolean updateByBo(TestTreeBo bo) {
+        TestTree update = BeanUtil.toBean(bo, TestTree.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+     *
+     * @param entity 瀹炰綋绫绘暟鎹�
+     */
+    private void validEntityBeforeSave(TestTree entity) {
+        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+        }
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+}
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/package-info.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/package-info.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/package-info.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/package-info.java
diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/package-info.java b/ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/package-info.java
similarity index 100%
rename from ruoyi-demo/src/main/java/com/ruoyi/demo/service/package-info.java
rename to ruoyi-modules/ruoyi-demo/src/main/java/com/ruoyi/demo/service/package-info.java
diff --git "a/ruoyi-demo/src/main/resources/excel/\345\215\225\345\210\227\350\241\250.xlsx" "b/ruoyi-modules/ruoyi-demo/src/main/resources/excel/\345\215\225\345\210\227\350\241\250.xlsx"
similarity index 100%
rename from "ruoyi-demo/src/main/resources/excel/\345\215\225\345\210\227\350\241\250.xlsx"
rename to "ruoyi-modules/ruoyi-demo/src/main/resources/excel/\345\215\225\345\210\227\350\241\250.xlsx"
Binary files differ
diff --git "a/ruoyi-demo/src/main/resources/excel/\345\244\232\345\210\227\350\241\250.xlsx" "b/ruoyi-modules/ruoyi-demo/src/main/resources/excel/\345\244\232\345\210\227\350\241\250.xlsx"
similarity index 100%
rename from "ruoyi-demo/src/main/resources/excel/\345\244\232\345\210\227\350\241\250.xlsx"
rename to "ruoyi-modules/ruoyi-demo/src/main/resources/excel/\345\244\232\345\210\227\350\241\250.xlsx"
Binary files differ
diff --git a/ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml b/ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml
similarity index 100%
rename from ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml
rename to ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml
diff --git a/ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml b/ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml
similarity index 100%
rename from ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml
rename to ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml
diff --git a/ruoyi-demo/src/main/resources/mapper/package-info.md b/ruoyi-modules/ruoyi-demo/src/main/resources/mapper/package-info.md
similarity index 100%
rename from ruoyi-demo/src/main/resources/mapper/package-info.md
rename to ruoyi-modules/ruoyi-demo/src/main/resources/mapper/package-info.md
diff --git a/ruoyi-modules/ruoyi-generator/pom.xml b/ruoyi-modules/ruoyi-generator/pom.xml
new file mode 100644
index 0000000..e4001ec
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/pom.xml
@@ -0,0 +1,48 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-modules</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-generator</artifactId>
+
+    <description>
+        generator 浠g爜鐢熸垚
+    </description>
+
+    <dependencies>
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-mybatis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-log</artifactId>
+        </dependency>
+
+        <!--velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
+        <dependency>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity-engine-core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
similarity index 100%
rename from ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
rename to ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
new file mode 100644
index 0000000..2a91434
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
@@ -0,0 +1,207 @@
+package com.ruoyi.generator.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.io.IoUtil;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.service.IGenTableService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/tool/gen")
+public class GenController extends BaseController {
+
+    private final IGenTableService genTableService;
+
+    /**
+     * 鏌ヨ浠g爜鐢熸垚鍒楄〃
+     */
+    @SaCheckPermission("tool:gen:list")
+    @GetMapping("/list")
+    public TableDataInfo<GenTable> genList(GenTable genTable, PageQuery pageQuery) {
+        return genTableService.selectPageGenTableList(genTable, pageQuery);
+    }
+
+    /**
+     * 淇敼浠g爜鐢熸垚涓氬姟
+     *
+     * @param tableId 琛↖D
+     */
+    @SaCheckPermission("tool:gen:query")
+    @GetMapping(value = "/{tableId}")
+    public R<Map<String, Object>> getInfo(@PathVariable Long tableId) {
+        GenTable table = genTableService.selectGenTableById(tableId);
+        List<GenTable> tables = genTableService.selectGenTableAll();
+        List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("info", table);
+        map.put("rows", list);
+        map.put("tables", tables);
+        return R.ok(map);
+    }
+
+    /**
+     * 鏌ヨ鏁版嵁搴撳垪琛�
+     */
+    @SaCheckPermission("tool:gen:list")
+    @GetMapping("/db/list")
+    public TableDataInfo<GenTable> dataList(GenTable genTable, PageQuery pageQuery) {
+        return genTableService.selectPageDbTableList(genTable, pageQuery);
+    }
+
+    /**
+     * 鏌ヨ鏁版嵁琛ㄥ瓧娈靛垪琛�
+     *
+     * @param tableId 琛↖D
+     */
+    @SaCheckPermission("tool:gen:list")
+    @GetMapping(value = "/column/{tableId}")
+    public TableDataInfo<GenTableColumn> columnList(Long tableId) {
+        TableDataInfo<GenTableColumn> dataInfo = new TableDataInfo<>();
+        List<GenTableColumn> list = genTableService.selectGenTableColumnListByTableId(tableId);
+        dataInfo.setRows(list);
+        dataInfo.setTotal(list.size());
+        return dataInfo;
+    }
+
+    /**
+     * 瀵煎叆琛ㄧ粨鏋勶紙淇濆瓨锛�
+     *
+     * @param tables 琛ㄥ悕涓�
+     */
+    @SaCheckPermission("tool:gen:import")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.IMPORT)
+    @PostMapping("/importTable")
+    public R<Void> importTableSave(String tables) {
+        String[] tableNames = Convert.toStrArray(tables);
+        // 鏌ヨ琛ㄤ俊鎭�
+        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
+        genTableService.importGenTable(tableList);
+        return R.ok();
+    }
+
+    /**
+     * 淇敼淇濆瓨浠g爜鐢熸垚涓氬姟
+     */
+    @SaCheckPermission("tool:gen:edit")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> editSave(@Validated @RequestBody GenTable genTable) {
+        genTableService.validateEdit(genTable);
+        genTableService.updateGenTable(genTable);
+        return R.ok();
+    }
+
+    /**
+     * 鍒犻櫎浠g爜鐢熸垚
+     *
+     * @param tableIds 琛↖D涓�
+     */
+    @SaCheckPermission("tool:gen:remove")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{tableIds}")
+    public R<Void> remove(@PathVariable Long[] tableIds) {
+        genTableService.deleteGenTableByIds(tableIds);
+        return R.ok();
+    }
+
+    /**
+     * 棰勮浠g爜
+     *
+     * @param tableId 琛↖D
+     */
+    @SaCheckPermission("tool:gen:preview")
+    @GetMapping("/preview/{tableId}")
+    public R<Map<String, String>> preview(@PathVariable("tableId") Long tableId) throws IOException {
+        Map<String, String> dataMap = genTableService.previewCode(tableId);
+        return R.ok(dataMap);
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     *
+     * @param tableName 琛ㄥ悕
+     */
+    @SaCheckPermission("tool:gen:code")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+    @GetMapping("/download/{tableName}")
+    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException {
+        byte[] data = genTableService.downloadCode(tableName);
+        genCode(response, data);
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+     *
+     * @param tableName 琛ㄥ悕
+     */
+    @SaCheckPermission("tool:gen:code")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+    @GetMapping("/genCode/{tableName}")
+    public R<Void> genCode(@PathVariable("tableName") String tableName) {
+        genTableService.generatorCode(tableName);
+        return R.ok();
+    }
+
+    /**
+     * 鍚屾鏁版嵁搴�
+     *
+     * @param tableName 琛ㄥ悕
+     */
+    @SaCheckPermission("tool:gen:edit")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+    @GetMapping("/synchDb/{tableName}")
+    public R<Void> synchDb(@PathVariable("tableName") String tableName) {
+        genTableService.synchDb(tableName);
+        return R.ok();
+    }
+
+    /**
+     * 鎵归噺鐢熸垚浠g爜
+     *
+     * @param tables 琛ㄥ悕涓�
+     */
+    @SaCheckPermission("tool:gen:code")
+    @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+    @GetMapping("/batchGenCode")
+    public void batchGenCode(HttpServletResponse response, String tables) throws IOException {
+        String[] tableNames = Convert.toStrArray(tables);
+        byte[] data = genTableService.downloadCode(tableNames);
+        genCode(response, data);
+    }
+
+    /**
+     * 鐢熸垚zip鏂囦欢
+     */
+    private void genCode(HttpServletResponse response, byte[] data) throws IOException {
+        response.reset();
+        response.addHeader("Access-Control-Allow-Origin", "*");
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
+        response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
+        response.addHeader("Content-Length", "" + data.length);
+        response.setContentType("application/octet-stream; charset=UTF-8");
+        IoUtil.write(response.getOutputStream(), false, data);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
new file mode 100644
index 0000000..7b8225c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
@@ -0,0 +1,192 @@
+package com.ruoyi.generator.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.ruoyi.common.core.constant.GenConstants;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.util.List;
+
+/**
+ * 涓氬姟琛� gen_table
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("gen_table")
+public class GenTable extends BaseEntity {
+
+    /**
+     * 缂栧彿
+     */
+    @TableId(value = "table_id")
+    private Long tableId;
+
+    /**
+     * 琛ㄥ悕绉�
+     */
+    @NotBlank(message = "琛ㄥ悕绉颁笉鑳戒负绌�")
+    private String tableName;
+
+    /**
+     * 琛ㄦ弿杩�
+     */
+    @NotBlank(message = "琛ㄦ弿杩颁笉鑳戒负绌�")
+    private String tableComment;
+
+    /**
+     * 鍏宠仈鐖惰〃鐨勮〃鍚�
+     */
+    private String subTableName;
+
+    /**
+     * 鏈〃鍏宠仈鐖惰〃鐨勫閿悕
+     */
+    private String subTableFkName;
+
+    /**
+     * 瀹炰綋绫诲悕绉�(棣栧瓧姣嶅ぇ鍐�)
+     */
+    @NotBlank(message = "瀹炰綋绫诲悕绉颁笉鑳戒负绌�")
+    private String className;
+
+    /**
+     * 浣跨敤鐨勬ā鏉匡紙crud鍗曡〃鎿嶄綔 tree鏍戣〃鎿嶄綔 sub涓诲瓙琛ㄦ搷浣滐級
+     */
+    private String tplCategory;
+
+    /**
+     * 鐢熸垚鍖呰矾寰�
+     */
+    @NotBlank(message = "鐢熸垚鍖呰矾寰勪笉鑳戒负绌�")
+    private String packageName;
+
+    /**
+     * 鐢熸垚妯″潡鍚�
+     */
+    @NotBlank(message = "鐢熸垚妯″潡鍚嶄笉鑳戒负绌�")
+    private String moduleName;
+
+    /**
+     * 鐢熸垚涓氬姟鍚�
+     */
+    @NotBlank(message = "鐢熸垚涓氬姟鍚嶄笉鑳戒负绌�")
+    private String businessName;
+
+    /**
+     * 鐢熸垚鍔熻兘鍚�
+     */
+    @NotBlank(message = "鐢熸垚鍔熻兘鍚嶄笉鑳戒负绌�")
+    private String functionName;
+
+    /**
+     * 鐢熸垚浣滆��
+     */
+    @NotBlank(message = "浣滆�呬笉鑳戒负绌�")
+    private String functionAuthor;
+
+    /**
+     * 鐢熸垚浠g爜鏂瑰紡锛�0zip鍘嬬缉鍖� 1鑷畾涔夎矾寰勶級
+     */
+    private String genType;
+
+    /**
+     * 鐢熸垚璺緞锛堜笉濉粯璁ら」鐩矾寰勶級
+     */
+    @TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+    private String genPath;
+
+    /**
+     * 涓婚敭淇℃伅
+     */
+    @TableField(exist = false)
+    private GenTableColumn pkColumn;
+
+    /**
+     * 琛ㄥ垪淇℃伅
+     */
+    @Valid
+    @TableField(exist = false)
+    private List<GenTableColumn> columns;
+
+    /**
+     * 鍏跺畠鐢熸垚閫夐」
+     */
+    private String options;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    /**
+     * 鏍戠紪鐮佸瓧娈�
+     */
+    @TableField(exist = false)
+    private String treeCode;
+
+    /**
+     * 鏍戠埗缂栫爜瀛楁
+     */
+    @TableField(exist = false)
+    private String treeParentCode;
+
+    /**
+     * 鏍戝悕绉板瓧娈�
+     */
+    @TableField(exist = false)
+    private String treeName;
+
+    /*
+     * 鑿滃崟id鍒楄〃
+     */
+    @TableField(exist = false)
+    private List<Long> menuIds;
+
+    /**
+     * 涓婄骇鑿滃崟ID瀛楁
+     */
+    @TableField(exist = false)
+    private String parentMenuId;
+
+    /**
+     * 涓婄骇鑿滃崟鍚嶇О瀛楁
+     */
+    @TableField(exist = false)
+    private String parentMenuName;
+
+    public boolean isTree() {
+        return isTree(this.tplCategory);
+    }
+
+    public static boolean isTree(String tplCategory) {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
+    }
+
+    public boolean isCrud() {
+        return isCrud(this.tplCategory);
+    }
+
+    public static boolean isCrud(String tplCategory) {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
+    }
+
+    public boolean isSuperColumn(String javaField) {
+        return isSuperColumn(this.tplCategory, javaField);
+    }
+
+    public static boolean isSuperColumn(String tplCategory, String javaField) {
+        if (isTree(tplCategory)) {
+            return StringUtils.equalsAnyIgnoreCase(javaField,
+                ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
+        }
+        return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
new file mode 100644
index 0000000..c743a30
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
@@ -0,0 +1,223 @@
+package com.ruoyi.generator.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.ibatis.type.JdbcType;
+
+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * 浠g爜鐢熸垚涓氬姟瀛楁琛� gen_table_column
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("gen_table_column")
+public class GenTableColumn extends BaseEntity {
+
+    /**
+     * 缂栧彿
+     */
+    @TableId(value = "column_id")
+    private Long columnId;
+
+    /**
+     * 褰掑睘琛ㄧ紪鍙�
+     */
+    private Long tableId;
+
+    /**
+     * 鍒楀悕绉�
+     */
+    private String columnName;
+
+    /**
+     * 鍒楁弿杩�
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String columnComment;
+
+    /**
+     * 鍒楃被鍨�
+     */
+    private String columnType;
+
+    /**
+     * JAVA绫诲瀷
+     */
+    private String javaType;
+
+    /**
+     * JAVA瀛楁鍚�
+     */
+    @NotBlank(message = "Java灞炴�т笉鑳戒负绌�")
+    private String javaField;
+
+    /**
+     * 鏄惁涓婚敭锛�1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isPk;
+
+    /**
+     * 鏄惁鑷锛�1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isIncrement;
+
+    /**
+     * 鏄惁蹇呭~锛�1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isRequired;
+
+    /**
+     * 鏄惁涓烘彃鍏ュ瓧娈碉紙1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isInsert;
+
+    /**
+     * 鏄惁缂栬緫瀛楁锛�1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isEdit;
+
+    /**
+     * 鏄惁鍒楄〃瀛楁锛�1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isList;
+
+    /**
+     * 鏄惁鏌ヨ瀛楁锛�1鏄級
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR)
+    private String isQuery;
+
+    /**
+     * 鏌ヨ鏂瑰紡锛圗Q绛変簬銆丯E涓嶇瓑浜庛�丟T澶т簬銆丩T灏忎簬銆丩IKE妯$硦銆丅ETWEEN鑼冨洿锛�
+     */
+    private String queryType;
+
+    /**
+     * 鏄剧ず绫诲瀷锛坕nput鏂囨湰妗嗐�乼extarea鏂囨湰鍩熴�乻elect涓嬫媺妗嗐�乧heckbox澶嶉�夋銆乺adio鍗曢�夋銆乨atetime鏃ユ湡鎺т欢銆乮mage鍥剧墖涓婁紶鎺т欢銆乽pload鏂囦欢涓婁紶鎺т欢銆乪ditor瀵屾枃鏈帶浠讹級
+     */
+    private String htmlType;
+
+    /**
+     * 瀛楀吀绫诲瀷
+     */
+    private String dictType;
+
+    /**
+     * 鎺掑簭
+     */
+    private Integer sort;
+
+    public String getCapJavaField() {
+        return StringUtils.capitalize(javaField);
+    }
+
+    public boolean isPk() {
+        return isPk(this.isPk);
+    }
+
+    public boolean isPk(String isPk) {
+        return isPk != null && StringUtils.equals("1", isPk);
+    }
+
+    public boolean isIncrement() {
+        return isIncrement(this.isIncrement);
+    }
+
+    public boolean isIncrement(String isIncrement) {
+        return isIncrement != null && StringUtils.equals("1", isIncrement);
+    }
+
+    public boolean isRequired() {
+        return isRequired(this.isRequired);
+    }
+
+    public boolean isRequired(String isRequired) {
+        return isRequired != null && StringUtils.equals("1", isRequired);
+    }
+
+    public boolean isInsert() {
+        return isInsert(this.isInsert);
+    }
+
+    public boolean isInsert(String isInsert) {
+        return isInsert != null && StringUtils.equals("1", isInsert);
+    }
+
+    public boolean isEdit() {
+        return isInsert(this.isEdit);
+    }
+
+    public boolean isEdit(String isEdit) {
+        return isEdit != null && StringUtils.equals("1", isEdit);
+    }
+
+    public boolean isList() {
+        return isList(this.isList);
+    }
+
+    public boolean isList(String isList) {
+        return isList != null && StringUtils.equals("1", isList);
+    }
+
+    public boolean isQuery() {
+        return isQuery(this.isQuery);
+    }
+
+    public boolean isQuery(String isQuery) {
+        return isQuery != null && StringUtils.equals("1", isQuery);
+    }
+
+    public boolean isSuperColumn() {
+        return isSuperColumn(this.javaField);
+    }
+
+    public static boolean isSuperColumn(String javaField) {
+        return StringUtils.equalsAnyIgnoreCase(javaField,
+            // BaseEntity
+            "createBy", "createTime", "updateBy", "updateTime",
+            // TreeEntity
+            "parentName", "parentId");
+    }
+
+    public boolean isUsableColumn() {
+        return isUsableColumn(javaField);
+    }
+
+    public static boolean isUsableColumn(String javaField) {
+        // isSuperColumn()涓殑鍚嶅崟鐢ㄤ簬閬垮厤鐢熸垚澶氫綑Domain灞炴�э紝鑻ユ煇浜涘睘鎬у湪鐢熸垚椤甸潰鏃堕渶瑕佺敤鍒颁笉鑳藉拷鐣ワ紝鍒欐斁鍦ㄦ澶勭櫧鍚嶅崟
+        return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
+    }
+
+    public String readConverterExp() {
+        String remarks = StringUtils.substringBetween(this.columnComment, "锛�", "锛�");
+        StringBuffer sb = new StringBuffer();
+        if (StringUtils.isNotEmpty(remarks)) {
+            for (String value : remarks.split(" ")) {
+                if (StringUtils.isNotEmpty(value)) {
+                    Object startStr = value.subSequence(0, 1);
+                    String endStr = value.substring(1);
+                    sb.append("").append(startStr).append("=").append(endStr).append(",");
+                }
+            }
+            return sb.deleteCharAt(sb.length() - 1).toString();
+        } else {
+            return this.columnComment;
+        }
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
new file mode 100644
index 0000000..6ae9e8e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.generator.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+import java.util.List;
+
+/**
+ * 涓氬姟瀛楁 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+@InterceptorIgnore(dataPermission = "true")
+public interface GenTableColumnMapper extends BaseMapperPlus<GenTableColumnMapper, GenTableColumn, GenTableColumn> {
+    /**
+     * 鏍规嵁琛ㄥ悕绉版煡璇㈠垪淇℃伅
+     *
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鍒椾俊鎭�
+     */
+    List<GenTableColumn> selectDbTableColumnsByName(String tableName);
+
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
new file mode 100644
index 0000000..b041fc3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
@@ -0,0 +1,58 @@
+package com.ruoyi.generator.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.generator.domain.GenTable;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 涓氬姟 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+@InterceptorIgnore(dataPermission = "true")
+public interface GenTableMapper extends BaseMapperPlus<GenTableMapper, GenTable, GenTable> {
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     *
+     * @param genTable 鏌ヨ鏉′欢
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    Page<GenTable> selectPageDbTableList(@Param("page") Page<GenTable> page, @Param("genTable") GenTable genTable);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     *
+     * @param tableNames 琛ㄥ悕绉扮粍
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+    /**
+     * 鏌ヨ鎵�鏈夎〃淇℃伅
+     *
+     * @return 琛ㄤ俊鎭泦鍚�
+     */
+    List<GenTable> selectGenTableAll();
+
+    /**
+     * 鏌ヨ琛↖D涓氬姟淇℃伅
+     *
+     * @param id 涓氬姟ID
+     * @return 涓氬姟淇℃伅
+     */
+    GenTable selectGenTableById(Long id);
+
+    /**
+     * 鏌ヨ琛ㄥ悕绉颁笟鍔′俊鎭�
+     *
+     * @param tableName 琛ㄥ悕绉�
+     * @return 涓氬姟淇℃伅
+     */
+    GenTable selectGenTableByName(String tableName);
+
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
new file mode 100644
index 0000000..37c7a82
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
@@ -0,0 +1,461 @@
+package com.ruoyi.generator.service;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.GenConstants;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.file.FileUtils;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+import com.ruoyi.generator.mapper.GenTableMapper;
+import com.ruoyi.generator.util.GenUtils;
+import com.ruoyi.generator.util.VelocityInitializer;
+import com.ruoyi.generator.util.VelocityUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * 涓氬姟 鏈嶅姟灞傚疄鐜�
+ *
+ * @author Lion Li
+ */
+@DS("#header.datasource")
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class GenTableServiceImpl implements IGenTableService {
+
+    private final GenTableMapper baseMapper;
+    private final GenTableColumnMapper genTableColumnMapper;
+    private final IdentifierGenerator identifierGenerator;
+
+    /**
+     * 鏌ヨ涓氬姟瀛楁鍒楄〃
+     *
+     * @param tableId 涓氬姟瀛楁缂栧彿
+     * @return 涓氬姟瀛楁闆嗗悎
+     */
+    @Override
+    public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId) {
+        return genTableColumnMapper.selectList(new LambdaQueryWrapper<GenTableColumn>()
+            .eq(GenTableColumn::getTableId, tableId)
+            .orderByAsc(GenTableColumn::getSort));
+    }
+
+    /**
+     * 鏌ヨ涓氬姟淇℃伅
+     *
+     * @param id 涓氬姟ID
+     * @return 涓氬姟淇℃伅
+     */
+    @Override
+    public GenTable selectGenTableById(Long id) {
+        GenTable genTable = baseMapper.selectGenTableById(id);
+        setTableFromOptions(genTable);
+        return genTable;
+    }
+
+    @Override
+    public TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery) {
+        Page<GenTable> page = baseMapper.selectPage(pageQuery.build(), this.buildGenTableQueryWrapper(genTable));
+        return TableDataInfo.build(page);
+    }
+
+    private QueryWrapper<GenTable> buildGenTableQueryWrapper(GenTable genTable) {
+        Map<String, Object> params = genTable.getParams();
+        QueryWrapper<GenTable> wrapper = Wrappers.query();
+        wrapper.like(StringUtils.isNotBlank(genTable.getTableName()), "lower(table_name)", StringUtils.lowerCase(genTable.getTableName()))
+            .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment()))
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                "create_time", params.get("beginTime"), params.get("endTime"));
+        return wrapper;
+    }
+
+
+    @Override
+    public TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery) {
+        Page<GenTable> page = baseMapper.selectPageDbTableList(pageQuery.build(), genTable);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     *
+     * @param tableNames 琛ㄥ悕绉扮粍
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    @Override
+    public List<GenTable> selectDbTableListByNames(String[] tableNames) {
+        return baseMapper.selectDbTableListByNames(tableNames);
+    }
+
+    /**
+     * 鏌ヨ鎵�鏈夎〃淇℃伅
+     *
+     * @return 琛ㄤ俊鎭泦鍚�
+     */
+    @Override
+    public List<GenTable> selectGenTableAll() {
+        return baseMapper.selectGenTableAll();
+    }
+
+    /**
+     * 淇敼涓氬姟
+     *
+     * @param genTable 涓氬姟淇℃伅
+     * @return 缁撴灉
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void updateGenTable(GenTable genTable) {
+        String options = JsonUtils.toJsonString(genTable.getParams());
+        genTable.setOptions(options);
+        int row = baseMapper.updateById(genTable);
+        if (row > 0) {
+            for (GenTableColumn cenTableColumn : genTable.getColumns()) {
+                genTableColumnMapper.updateById(cenTableColumn);
+            }
+        }
+    }
+
+    /**
+     * 鍒犻櫎涓氬姟瀵硅薄
+     *
+     * @param tableIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void deleteGenTableByIds(Long[] tableIds) {
+        List<Long> ids = Arrays.asList(tableIds);
+        baseMapper.deleteBatchIds(ids);
+        genTableColumnMapper.delete(new LambdaQueryWrapper<GenTableColumn>().in(GenTableColumn::getTableId, ids));
+    }
+
+    /**
+     * 瀵煎叆琛ㄧ粨鏋�
+     *
+     * @param tableList 瀵煎叆琛ㄥ垪琛�
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void importGenTable(List<GenTable> tableList) {
+        String operName = LoginHelper.getUsername();
+        try {
+            for (GenTable table : tableList) {
+                String tableName = table.getTableName();
+                GenUtils.initTable(table, operName);
+                int row = baseMapper.insert(table);
+                if (row > 0) {
+                    // 淇濆瓨鍒椾俊鎭�
+                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+                    List<GenTableColumn> saveColumns = new ArrayList<>();
+                    for (GenTableColumn column : genTableColumns) {
+                        GenUtils.initColumnField(column, table);
+                        saveColumns.add(column);
+                    }
+                    if (CollUtil.isNotEmpty(saveColumns)) {
+                        genTableColumnMapper.insertBatch(saveColumns);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new ServiceException("瀵煎叆澶辫触锛�" + e.getMessage());
+        }
+    }
+
+    /**
+     * 棰勮浠g爜
+     *
+     * @param tableId 琛ㄧ紪鍙�
+     * @return 棰勮鏁版嵁鍒楄〃
+     */
+    @Override
+    public Map<String, String> previewCode(Long tableId) {
+        Map<String, String> dataMap = new LinkedHashMap<>();
+        // 鏌ヨ琛ㄤ俊鎭�
+        GenTable table = baseMapper.selectGenTableById(tableId);
+        List<Long> menuIds = new ArrayList<>();
+        for (int i = 0; i < 6; i++) {
+            menuIds.add(identifierGenerator.nextId(null).longValue());
+        }
+        table.setMenuIds(menuIds);
+        // 璁剧疆涓婚敭鍒椾俊鎭�
+        setPkColumn(table);
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 鑾峰彇妯℃澘鍒楄〃
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
+        for (String template : templates) {
+            // 娓叉煋妯℃澘
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            dataMap.put(template, sw.toString());
+        }
+        return dataMap;
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     *
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鏁版嵁
+     */
+    @Override
+    public byte[] downloadCode(String tableName) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        generatorCode(tableName, zip);
+        IoUtil.close(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+     *
+     * @param tableName 琛ㄥ悕绉�
+     */
+    @Override
+    public void generatorCode(String tableName) {
+        // 鏌ヨ琛ㄤ俊鎭�
+        GenTable table = baseMapper.selectGenTableByName(tableName);
+        // 璁剧疆涓婚敭鍒椾俊鎭�
+        setPkColumn(table);
+
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 鑾峰彇妯℃澘鍒楄〃
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
+        for (String template : templates) {
+            if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) {
+                // 娓叉煋妯℃澘
+                StringWriter sw = new StringWriter();
+                Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+                tpl.merge(context, sw);
+                try {
+                    String path = getGenPath(table, template);
+                    FileUtils.writeUtf8String(sw.toString(), path);
+                } catch (Exception e) {
+                    throw new ServiceException("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName());
+                }
+            }
+        }
+    }
+
+    /**
+     * 鍚屾鏁版嵁搴�
+     *
+     * @param tableName 琛ㄥ悕绉�
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void synchDb(String tableName) {
+        GenTable table = baseMapper.selectGenTableByName(tableName);
+        List<GenTableColumn> tableColumns = table.getColumns();
+        Map<String, GenTableColumn> tableColumnMap = StreamUtils.toIdentityMap(tableColumns, GenTableColumn::getColumnName);
+
+        List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+        if (CollUtil.isEmpty(dbTableColumns)) {
+            throw new ServiceException("鍚屾鏁版嵁澶辫触锛屽師琛ㄧ粨鏋勪笉瀛樺湪");
+        }
+        List<String> dbTableColumnNames = StreamUtils.toList(dbTableColumns, GenTableColumn::getColumnName);
+
+        List<GenTableColumn> saveColumns = new ArrayList<>();
+        dbTableColumns.forEach(column -> {
+            GenUtils.initColumnField(column, table);
+            if (tableColumnMap.containsKey(column.getColumnName())) {
+                GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
+                column.setColumnId(prevColumn.getColumnId());
+                if (column.isList()) {
+                    // 濡傛灉鏄垪琛紝缁х画淇濈暀鏌ヨ鏂瑰紡/瀛楀吀绫诲瀷閫夐」
+                    column.setDictType(prevColumn.getDictType());
+                    column.setQueryType(prevColumn.getQueryType());
+                }
+                if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
+                    && (column.isInsert() || column.isEdit())
+                    && ((column.isUsableColumn()) || (!column.isSuperColumn()))) {
+                    // 濡傛灉鏄�(鏂板/淇敼&闈炰富閿�/闈炲拷鐣ュ強鐖跺睘鎬�)锛岀户缁繚鐣欏繀濉�/鏄剧ず绫诲瀷閫夐」
+                    column.setIsRequired(prevColumn.getIsRequired());
+                    column.setHtmlType(prevColumn.getHtmlType());
+                }
+                genTableColumnMapper.updateById(column);
+            } else {
+                genTableColumnMapper.insert(column);
+            }
+        });
+        if (CollUtil.isNotEmpty(saveColumns)) {
+            genTableColumnMapper.insertBatch(saveColumns);
+        }
+        List<GenTableColumn> delColumns = StreamUtils.filter(tableColumns, column -> !dbTableColumnNames.contains(column.getColumnName()));
+        if (CollUtil.isNotEmpty(delColumns)) {
+            List<Long> ids = StreamUtils.toList(delColumns, GenTableColumn::getColumnId);
+            genTableColumnMapper.deleteBatchIds(ids);
+        }
+    }
+
+    /**
+     * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     *
+     * @param tableNames 琛ㄦ暟缁�
+     * @return 鏁版嵁
+     */
+    @Override
+    public byte[] downloadCode(String[] tableNames) {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        for (String tableName : tableNames) {
+            generatorCode(tableName, zip);
+        }
+        IoUtil.close(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 鏌ヨ琛ㄤ俊鎭苟鐢熸垚浠g爜
+     */
+    private void generatorCode(String tableName, ZipOutputStream zip) {
+        // 鏌ヨ琛ㄤ俊鎭�
+        GenTable table = baseMapper.selectGenTableByName(tableName);
+        List<Long> menuIds = new ArrayList<>();
+        for (int i = 0; i < 6; i++) {
+            menuIds.add(identifierGenerator.nextId(null).longValue());
+        }
+        table.setMenuIds(menuIds);
+        // 璁剧疆涓婚敭鍒椾俊鎭�
+        setPkColumn(table);
+
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 鑾峰彇妯℃澘鍒楄〃
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
+        for (String template : templates) {
+            // 娓叉煋妯℃澘
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            try {
+                // 娣诲姞鍒皕ip
+                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
+                IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
+                IoUtil.close(sw);
+                zip.flush();
+                zip.closeEntry();
+            } catch (IOException e) {
+                log.error("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName(), e);
+            }
+        }
+    }
+
+    /**
+     * 淇敼淇濆瓨鍙傛暟鏍¢獙
+     *
+     * @param genTable 涓氬姟淇℃伅
+     */
+    @Override
+    public void validateEdit(GenTable genTable) {
+        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
+            String options = JsonUtils.toJsonString(genTable.getParams());
+            Dict paramsObj = JsonUtils.parseMap(options);
+            if (StringUtils.isEmpty(paramsObj.getStr(GenConstants.TREE_CODE))) {
+                throw new ServiceException("鏍戠紪鐮佸瓧娈典笉鑳戒负绌�");
+            } else if (StringUtils.isEmpty(paramsObj.getStr(GenConstants.TREE_PARENT_CODE))) {
+                throw new ServiceException("鏍戠埗缂栫爜瀛楁涓嶈兘涓虹┖");
+            } else if (StringUtils.isEmpty(paramsObj.getStr(GenConstants.TREE_NAME))) {
+                throw new ServiceException("鏍戝悕绉板瓧娈典笉鑳戒负绌�");
+            }
+        }
+    }
+
+    /**
+     * 璁剧疆涓婚敭鍒椾俊鎭�
+     *
+     * @param table 涓氬姟琛ㄤ俊鎭�
+     */
+    public void setPkColumn(GenTable table) {
+        for (GenTableColumn column : table.getColumns()) {
+            if (column.isPk()) {
+                table.setPkColumn(column);
+                break;
+            }
+        }
+        if (ObjectUtil.isNull(table.getPkColumn())) {
+            table.setPkColumn(table.getColumns().get(0));
+        }
+
+    }
+
+    /**
+     * 璁剧疆浠g爜鐢熸垚鍏朵粬閫夐」鍊�
+     *
+     * @param genTable 璁剧疆鍚庣殑鐢熸垚瀵硅薄
+     */
+    public void setTableFromOptions(GenTable genTable) {
+        Dict paramsObj = JsonUtils.parseMap(genTable.getOptions());
+        if (ObjectUtil.isNotNull(paramsObj)) {
+            String treeCode = paramsObj.getStr(GenConstants.TREE_CODE);
+            String treeParentCode = paramsObj.getStr(GenConstants.TREE_PARENT_CODE);
+            String treeName = paramsObj.getStr(GenConstants.TREE_NAME);
+            String parentMenuId = paramsObj.getStr(GenConstants.PARENT_MENU_ID);
+            String parentMenuName = paramsObj.getStr(GenConstants.PARENT_MENU_NAME);
+
+            genTable.setTreeCode(treeCode);
+            genTable.setTreeParentCode(treeParentCode);
+            genTable.setTreeName(treeName);
+            genTable.setParentMenuId(parentMenuId);
+            genTable.setParentMenuName(parentMenuName);
+        }
+    }
+
+    /**
+     * 鑾峰彇浠g爜鐢熸垚鍦板潃
+     *
+     * @param table    涓氬姟琛ㄤ俊鎭�
+     * @param template 妯℃澘鏂囦欢璺緞
+     * @return 鐢熸垚鍦板潃
+     */
+    public static String getGenPath(GenTable table, String template) {
+        String genPath = table.getGenPath();
+        if (StringUtils.equals(genPath, "/")) {
+            return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
+        }
+        return genPath + File.separator + VelocityUtils.getFileName(template, table);
+    }
+}
+
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
new file mode 100644
index 0000000..3e6727f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
@@ -0,0 +1,133 @@
+package com.ruoyi.generator.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 涓氬姟 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface IGenTableService {
+
+    /**
+     * 鏌ヨ涓氬姟瀛楁鍒楄〃
+     *
+     * @param tableId 涓氬姟瀛楁缂栧彿
+     * @return 涓氬姟瀛楁闆嗗悎
+     */
+    List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
+
+    /**
+     * 鏌ヨ涓氬姟鍒楄〃
+     *
+     * @param genTable 涓氬姟淇℃伅
+     * @return 涓氬姟闆嗗悎
+     */
+    TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     *
+     * @param genTable 涓氬姟淇℃伅
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ鎹簱鍒楄〃
+     *
+     * @param tableNames 琛ㄥ悕绉扮粍
+     * @return 鏁版嵁搴撹〃闆嗗悎
+     */
+    List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+    /**
+     * 鏌ヨ鎵�鏈夎〃淇℃伅
+     *
+     * @return 琛ㄤ俊鎭泦鍚�
+     */
+    List<GenTable> selectGenTableAll();
+
+    /**
+     * 鏌ヨ涓氬姟淇℃伅
+     *
+     * @param id 涓氬姟ID
+     * @return 涓氬姟淇℃伅
+     */
+    GenTable selectGenTableById(Long id);
+
+    /**
+     * 淇敼涓氬姟
+     *
+     * @param genTable 涓氬姟淇℃伅
+     * @return 缁撴灉
+     */
+    void updateGenTable(GenTable genTable);
+
+    /**
+     * 鍒犻櫎涓氬姟淇℃伅
+     *
+     * @param tableIds 闇�瑕佸垹闄ょ殑琛ㄦ暟鎹甀D
+     * @return 缁撴灉
+     */
+    void deleteGenTableByIds(Long[] tableIds);
+
+    /**
+     * 瀵煎叆琛ㄧ粨鏋�
+     *
+     * @param tableList 瀵煎叆琛ㄥ垪琛�
+     */
+    void importGenTable(List<GenTable> tableList);
+
+    /**
+     * 棰勮浠g爜
+     *
+     * @param tableId 琛ㄧ紪鍙�
+     * @return 棰勮鏁版嵁鍒楄〃
+     */
+    Map<String, String> previewCode(Long tableId);
+
+    /**
+     * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     *
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鏁版嵁
+     */
+    byte[] downloadCode(String tableName);
+
+    /**
+     * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+     *
+     * @param tableName 琛ㄥ悕绉�
+     * @return 鏁版嵁
+     */
+    void generatorCode(String tableName);
+
+    /**
+     * 鍚屾鏁版嵁搴�
+     *
+     * @param tableName 琛ㄥ悕绉�
+     */
+    void synchDb(String tableName);
+
+    /**
+     * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+     *
+     * @param tableNames 琛ㄦ暟缁�
+     * @return 鏁版嵁
+     */
+    byte[] downloadCode(String[] tableNames);
+
+    /**
+     * 淇敼淇濆瓨鍙傛暟鏍¢獙
+     *
+     * @param genTable 涓氬姟淇℃伅
+     */
+    void validateEdit(GenTable genTable);
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
new file mode 100644
index 0000000..cb0a065
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
@@ -0,0 +1,232 @@
+package com.ruoyi.generator.util;
+
+import com.ruoyi.common.core.constant.GenConstants;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.RegExUtils;
+
+import java.util.Arrays;
+
+/**
+ * 浠g爜鐢熸垚鍣� 宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class GenUtils {
+
+    /**
+     * 鍒濆鍖栬〃淇℃伅
+     */
+    public static void initTable(GenTable genTable, String operName) {
+        genTable.setClassName(convertClassName(genTable.getTableName()));
+        genTable.setPackageName(GenConfig.getPackageName());
+        genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
+        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
+        genTable.setFunctionName(replaceText(genTable.getTableComment()));
+        genTable.setFunctionAuthor(GenConfig.getAuthor());
+        genTable.setCreateBy(operName);
+    }
+
+    /**
+     * 鍒濆鍖栧垪灞炴�у瓧娈�
+     */
+    public static void initColumnField(GenTableColumn column, GenTable table) {
+        String dataType = getDbType(column.getColumnType());
+        String columnName = column.getColumnName();
+        column.setTableId(table.getTableId());
+        column.setCreateBy(table.getCreateBy());
+        // 璁剧疆java瀛楁鍚�
+        column.setJavaField(StringUtils.toCamelCase(columnName));
+        // 璁剧疆榛樿绫诲瀷
+        column.setJavaType(GenConstants.TYPE_STRING);
+        column.setQueryType(GenConstants.QUERY_EQ);
+
+        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) {
+            // 瀛楃涓查暱搴﹁秴杩�500璁剧疆涓烘枃鏈煙
+            Integer columnLength = getColumnLength(column.getColumnType());
+            String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
+            column.setHtmlType(htmlType);
+        } else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) {
+            column.setJavaType(GenConstants.TYPE_DATE);
+            column.setHtmlType(GenConstants.HTML_DATETIME);
+        } else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) {
+            column.setHtmlType(GenConstants.HTML_INPUT);
+
+            // 濡傛灉鏄诞鐐瑰瀷 缁熶竴鐢˙igDecimal
+            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
+            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) {
+                column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
+            }
+            // 濡傛灉鏄暣褰�
+            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) {
+                column.setJavaType(GenConstants.TYPE_INTEGER);
+            }
+            // 闀挎暣褰�
+            else {
+                column.setJavaType(GenConstants.TYPE_LONG);
+            }
+        }
+
+        // BO瀵硅薄 榛樿鎻掑叆鍕鹃��
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_ADD, columnName) && !column.isPk()) {
+            column.setIsInsert(GenConstants.REQUIRE);
+        }
+        // BO瀵硅薄 榛樿缂栬緫鍕鹃��
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) {
+            column.setIsEdit(GenConstants.REQUIRE);
+        }
+        // BO瀵硅薄 榛樿鏄惁蹇呭~鍕鹃��
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName)) {
+            column.setIsRequired(GenConstants.REQUIRE);
+        }
+        // VO瀵硅薄 榛樿杩斿洖鍕鹃��
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName)) {
+            column.setIsList(GenConstants.REQUIRE);
+        }
+        // BO瀵硅薄 榛樿鏌ヨ鍕鹃��
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) {
+            column.setIsQuery(GenConstants.REQUIRE);
+        }
+
+        // 鏌ヨ瀛楁绫诲瀷
+        if (StringUtils.endsWithIgnoreCase(columnName, "name")) {
+            column.setQueryType(GenConstants.QUERY_LIKE);
+        }
+        // 鐘舵�佸瓧娈佃缃崟閫夋
+        if (StringUtils.endsWithIgnoreCase(columnName, "status")) {
+            column.setHtmlType(GenConstants.HTML_RADIO);
+        }
+        // 绫诲瀷&鎬у埆瀛楁璁剧疆涓嬫媺妗�
+        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
+            || StringUtils.endsWithIgnoreCase(columnName, "sex")) {
+            column.setHtmlType(GenConstants.HTML_SELECT);
+        }
+        // 鍥剧墖瀛楁璁剧疆鍥剧墖涓婁紶鎺т欢
+        else if (StringUtils.endsWithIgnoreCase(columnName, "image")) {
+            column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
+        }
+        // 鏂囦欢瀛楁璁剧疆鏂囦欢涓婁紶鎺т欢
+        else if (StringUtils.endsWithIgnoreCase(columnName, "file")) {
+            column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
+        }
+        // 鍐呭瀛楁璁剧疆瀵屾枃鏈帶浠�
+        else if (StringUtils.endsWithIgnoreCase(columnName, "content")) {
+            column.setHtmlType(GenConstants.HTML_EDITOR);
+        }
+    }
+
+    /**
+     * 鏍¢獙鏁扮粍鏄惁鍖呭惈鎸囧畾鍊�
+     *
+     * @param arr         鏁扮粍
+     * @param targetValue 鍊�
+     * @return 鏄惁鍖呭惈
+     */
+    public static boolean arraysContains(String[] arr, String targetValue) {
+        return Arrays.asList(arr).contains(targetValue);
+    }
+
+    /**
+     * 鑾峰彇妯″潡鍚�
+     *
+     * @param packageName 鍖呭悕
+     * @return 妯″潡鍚�
+     */
+    public static String getModuleName(String packageName) {
+        int lastIndex = packageName.lastIndexOf(".");
+        int nameLength = packageName.length();
+        return StringUtils.substring(packageName, lastIndex + 1, nameLength);
+    }
+
+    /**
+     * 鑾峰彇涓氬姟鍚�
+     *
+     * @param tableName 琛ㄥ悕
+     * @return 涓氬姟鍚�
+     */
+    public static String getBusinessName(String tableName) {
+        int firstIndex = tableName.indexOf("_");
+        int nameLength = tableName.length();
+        String businessName = StringUtils.substring(tableName, firstIndex + 1, nameLength);
+        businessName = StringUtils.toCamelCase(businessName);
+        return businessName;
+    }
+
+    /**
+     * 琛ㄥ悕杞崲鎴怞ava绫诲悕
+     *
+     * @param tableName 琛ㄥ悕绉�
+     * @return 绫诲悕
+     */
+    public static String convertClassName(String tableName) {
+        boolean autoRemovePre = GenConfig.getAutoRemovePre();
+        String tablePrefix = GenConfig.getTablePrefix();
+        if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) {
+            String[] searchList = StringUtils.split(tablePrefix, ",");
+            tableName = replaceFirst(tableName, searchList);
+        }
+        return StringUtils.convertToCamelCase(tableName);
+    }
+
+    /**
+     * 鎵归噺鏇挎崲鍓嶇紑
+     *
+     * @param replacementm 鏇挎崲鍊�
+     * @param searchList   鏇挎崲鍒楄〃
+     * @return
+     */
+    public static String replaceFirst(String replacementm, String[] searchList) {
+        String text = replacementm;
+        for (String searchString : searchList) {
+            if (replacementm.startsWith(searchString)) {
+                text = replacementm.replaceFirst(searchString, "");
+                break;
+            }
+        }
+        return text;
+    }
+
+    /**
+     * 鍏抽敭瀛楁浛鎹�
+     *
+     * @param text 闇�瑕佽鏇挎崲鐨勫悕瀛�
+     * @return 鏇挎崲鍚庣殑鍚嶅瓧
+     */
+    public static String replaceText(String text) {
+        return RegExUtils.replaceAll(text, "(?:琛▅鑻ヤ緷)", "");
+    }
+
+    /**
+     * 鑾峰彇鏁版嵁搴撶被鍨嬪瓧娈�
+     *
+     * @param columnType 鍒楃被鍨�
+     * @return 鎴彇鍚庣殑鍒楃被鍨�
+     */
+    public static String getDbType(String columnType) {
+        if (StringUtils.indexOf(columnType, '(') > 0) {
+            return StringUtils.substringBefore(columnType, "(");
+        } else {
+            return columnType;
+        }
+    }
+
+    /**
+     * 鑾峰彇瀛楁闀垮害
+     *
+     * @param columnType 鍒楃被鍨�
+     * @return 鎴彇鍚庣殑鍒楃被鍨�
+     */
+    public static Integer getColumnLength(String columnType) {
+        if (StringUtils.indexOf(columnType, '(') > 0) {
+            String length = StringUtils.substringBetween(columnType, "(", ")");
+            return Integer.valueOf(length);
+        } else {
+            return 0;
+        }
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
new file mode 100644
index 0000000..045e303
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
@@ -0,0 +1,35 @@
+package com.ruoyi.generator.util;
+
+import com.ruoyi.common.core.constant.Constants;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.velocity.app.Velocity;
+
+import java.util.Properties;
+
+/**
+ * VelocityEngine宸ュ巶
+ *
+ * @author ruoyi
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class VelocityInitializer {
+
+    /**
+     * 鍒濆鍖杤m鏂规硶
+     */
+    public static void initVelocity() {
+        Properties p = new Properties();
+        try {
+            // 鍔犺浇classpath鐩綍涓嬬殑vm鏂囦欢
+            p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+            // 瀹氫箟瀛楃闆�
+            p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
+            // 鍒濆鍖朧elocity寮曟搸锛屾寚瀹氶厤缃甈roperties
+            Velocity.init(p);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
new file mode 100644
index 0000000..e23b08d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
@@ -0,0 +1,336 @@
+package com.ruoyi.generator.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.core.constant.GenConstants;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.mybatis.helper.DataBaseHelper;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.velocity.VelocityContext;
+
+import java.util.*;
+
+/**
+ * 妯℃澘澶勭悊宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class VelocityUtils {
+
+    /**
+     * 椤圭洰绌洪棿璺緞
+     */
+    private static final String PROJECT_PATH = "main/java";
+
+    /**
+     * mybatis绌洪棿璺緞
+     */
+    private static final String MYBATIS_PATH = "main/resources/mapper";
+
+    /**
+     * 榛樿涓婄骇鑿滃崟锛岀郴缁熷伐鍏�
+     */
+    private static final String DEFAULT_PARENT_MENU_ID = "3";
+
+    /**
+     * 璁剧疆妯℃澘鍙橀噺淇℃伅
+     *
+     * @return 妯℃澘鍒楄〃
+     */
+    public static VelocityContext prepareContext(GenTable genTable) {
+        String moduleName = genTable.getModuleName();
+        String businessName = genTable.getBusinessName();
+        String packageName = genTable.getPackageName();
+        String tplCategory = genTable.getTplCategory();
+        String functionName = genTable.getFunctionName();
+
+        VelocityContext velocityContext = new VelocityContext();
+        velocityContext.put("tplCategory", genTable.getTplCategory());
+        velocityContext.put("tableName", genTable.getTableName());
+        velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "銆愯濉啓鍔熻兘鍚嶇О銆�");
+        velocityContext.put("ClassName", genTable.getClassName());
+        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
+        velocityContext.put("moduleName", genTable.getModuleName());
+        velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
+        velocityContext.put("businessName", genTable.getBusinessName());
+        velocityContext.put("basePackage", getPackagePrefix(packageName));
+        velocityContext.put("packageName", packageName);
+        velocityContext.put("author", genTable.getFunctionAuthor());
+        velocityContext.put("datetime", DateUtils.getDate());
+        velocityContext.put("pkColumn", genTable.getPkColumn());
+        velocityContext.put("importList", getImportList(genTable));
+        velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
+        velocityContext.put("columns", genTable.getColumns());
+        velocityContext.put("table", genTable);
+        velocityContext.put("dicts", getDicts(genTable));
+        setMenuVelocityContext(velocityContext, genTable);
+        if (GenConstants.TPL_TREE.equals(tplCategory)) {
+            setTreeVelocityContext(velocityContext, genTable);
+        }
+        return velocityContext;
+    }
+
+    public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) {
+        String options = genTable.getOptions();
+        Dict paramsObj = JsonUtils.parseMap(options);
+        String parentMenuId = getParentMenuId(paramsObj);
+        context.put("parentMenuId", parentMenuId);
+    }
+
+    public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) {
+        String options = genTable.getOptions();
+        Dict paramsObj = JsonUtils.parseMap(options);
+        String treeCode = getTreecode(paramsObj);
+        String treeParentCode = getTreeParentCode(paramsObj);
+        String treeName = getTreeName(paramsObj);
+
+        context.put("treeCode", treeCode);
+        context.put("treeParentCode", treeParentCode);
+        context.put("treeName", treeName);
+        context.put("expandColumn", getExpandColumn(genTable));
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
+            context.put("tree_parent_code", paramsObj.get(GenConstants.TREE_PARENT_CODE));
+        }
+        if (paramsObj.containsKey(GenConstants.TREE_NAME)) {
+            context.put("tree_name", paramsObj.get(GenConstants.TREE_NAME));
+        }
+    }
+
+    /**
+     * 鑾峰彇妯℃澘淇℃伅
+     *
+     * @return 妯℃澘鍒楄〃
+     */
+    public static List<String> getTemplateList(String tplCategory) {
+        List<String> templates = new ArrayList<String>();
+        templates.add("vm/java/domain.java.vm");
+        templates.add("vm/java/vo.java.vm");
+        templates.add("vm/java/bo.java.vm");
+        templates.add("vm/java/mapper.java.vm");
+        templates.add("vm/java/service.java.vm");
+        templates.add("vm/java/serviceImpl.java.vm");
+        templates.add("vm/java/controller.java.vm");
+        templates.add("vm/xml/mapper.xml.vm");
+        if (DataBaseHelper.isOracle()) {
+            templates.add("vm/sql/oracle/sql.vm");
+        } else if (DataBaseHelper.isPostgerSql()) {
+            templates.add("vm/sql/postgres/sql.vm");
+        } else if (DataBaseHelper.isSqlServer()) {
+            templates.add("vm/sql/sqlserver/sql.vm");
+        } else {
+            templates.add("vm/sql/sql.vm");
+        }
+        templates.add("vm/js/api.js.vm");
+        if (GenConstants.TPL_CRUD.equals(tplCategory)) {
+            templates.add("vm/vue/index.vue.vm");
+        } else if (GenConstants.TPL_TREE.equals(tplCategory)) {
+            templates.add("vm/vue/index-tree.vue.vm");
+        }
+        return templates;
+    }
+
+    /**
+     * 鑾峰彇鏂囦欢鍚�
+     */
+    public static String getFileName(String template, GenTable genTable) {
+        // 鏂囦欢鍚嶇О
+        String fileName = "";
+        // 鍖呰矾寰�
+        String packageName = genTable.getPackageName();
+        // 妯″潡鍚�
+        String moduleName = genTable.getModuleName();
+        // 澶у啓绫诲悕
+        String className = genTable.getClassName();
+        // 涓氬姟鍚嶇О
+        String businessName = genTable.getBusinessName();
+
+        String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
+        String mybatisPath = MYBATIS_PATH + "/" + moduleName;
+        String vuePath = "vue";
+
+        if (template.contains("domain.java.vm")) {
+            fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
+        }
+        if (template.contains("vo.java.vm")) {
+            fileName = StringUtils.format("{}/domain/vo/{}Vo.java", javaPath, className);
+        }
+        if (template.contains("bo.java.vm")) {
+            fileName = StringUtils.format("{}/domain/bo/{}Bo.java", javaPath, className);
+        }
+        if (template.contains("mapper.java.vm")) {
+            fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
+        } else if (template.contains("service.java.vm")) {
+            fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
+        } else if (template.contains("serviceImpl.java.vm")) {
+            fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
+        } else if (template.contains("controller.java.vm")) {
+            fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
+        } else if (template.contains("mapper.xml.vm")) {
+            fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
+        } else if (template.contains("sql.vm")) {
+            fileName = businessName + "Menu.sql";
+        } else if (template.contains("api.js.vm")) {
+            fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
+        } else if (template.contains("index.vue.vm")) {
+            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+        } else if (template.contains("index-tree.vue.vm")) {
+            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+        }
+        return fileName;
+    }
+
+    /**
+     * 鑾峰彇鍖呭墠缂�
+     *
+     * @param packageName 鍖呭悕绉�
+     * @return 鍖呭墠缂�鍚嶇О
+     */
+    public static String getPackagePrefix(String packageName) {
+        int lastIndex = packageName.lastIndexOf(".");
+        return StringUtils.substring(packageName, 0, lastIndex);
+    }
+
+    /**
+     * 鏍规嵁鍒楃被鍨嬭幏鍙栧鍏ュ寘
+     *
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 杩斿洖闇�瑕佸鍏ョ殑鍖呭垪琛�
+     */
+    public static HashSet<String> getImportList(GenTable genTable) {
+        List<GenTableColumn> columns = genTable.getColumns();
+        HashSet<String> importList = new HashSet<String>();
+        for (GenTableColumn column : columns) {
+            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) {
+                importList.add("java.util.Date");
+                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
+            } else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) {
+                importList.add("java.math.BigDecimal");
+            }
+        }
+        return importList;
+    }
+
+    /**
+     * 鏍规嵁鍒楃被鍨嬭幏鍙栧瓧鍏哥粍
+     *
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 杩斿洖瀛楀吀缁�
+     */
+    public static String getDicts(GenTable genTable) {
+        List<GenTableColumn> columns = genTable.getColumns();
+        Set<String> dicts = new HashSet<String>();
+        addDicts(dicts, columns);
+        return StringUtils.join(dicts, ", ");
+    }
+
+    /**
+     * 娣诲姞瀛楀吀鍒楄〃
+     *
+     * @param dicts 瀛楀吀鍒楄〃
+     * @param columns 鍒楅泦鍚�
+     */
+    public static void addDicts(Set<String> dicts, List<GenTableColumn> columns) {
+        for (GenTableColumn column : columns) {
+            if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
+                column.getHtmlType(),
+                new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) {
+                dicts.add("'" + column.getDictType() + "'");
+            }
+        }
+    }
+
+    /**
+     * 鑾峰彇鏉冮檺鍓嶇紑
+     *
+     * @param moduleName   妯″潡鍚嶇О
+     * @param businessName 涓氬姟鍚嶇О
+     * @return 杩斿洖鏉冮檺鍓嶇紑
+     */
+    public static String getPermissionPrefix(String moduleName, String businessName) {
+        return StringUtils.format("{}:{}", moduleName, businessName);
+    }
+
+    /**
+     * 鑾峰彇涓婄骇鑿滃崟ID瀛楁
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 涓婄骇鑿滃崟ID瀛楁
+     */
+    public static String getParentMenuId(Dict paramsObj) {
+        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
+            && StringUtils.isNotEmpty(paramsObj.getStr(GenConstants.PARENT_MENU_ID))) {
+            return paramsObj.getStr(GenConstants.PARENT_MENU_ID);
+        }
+        return DEFAULT_PARENT_MENU_ID;
+    }
+
+    /**
+     * 鑾峰彇鏍戠紪鐮�
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 鏍戠紪鐮�
+     */
+    public static String getTreecode(Map<String, Object> paramsObj) {
+        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_CODE)) {
+            return StringUtils.toCamelCase(Convert.toStr(paramsObj.get(GenConstants.TREE_CODE)));
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇鏍戠埗缂栫爜
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 鏍戠埗缂栫爜
+     */
+    public static String getTreeParentCode(Dict paramsObj) {
+        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
+            return StringUtils.toCamelCase(paramsObj.getStr(GenConstants.TREE_PARENT_CODE));
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇鏍戝悕绉�
+     *
+     * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+     * @return 鏍戝悕绉�
+     */
+    public static String getTreeName(Dict paramsObj) {
+        if (CollUtil.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.TREE_NAME)) {
+            return StringUtils.toCamelCase(paramsObj.getStr(GenConstants.TREE_NAME));
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇闇�瑕佸湪鍝竴鍒椾笂闈㈡樉绀哄睍寮�鎸夐挳
+     *
+     * @param genTable 涓氬姟琛ㄥ璞�
+     * @return 灞曞紑鎸夐挳鍒楀簭鍙�
+     */
+    public static int getExpandColumn(GenTable genTable) {
+        String options = genTable.getOptions();
+        Dict paramsObj = JsonUtils.parseMap(options);
+        String treeName = paramsObj.getStr(GenConstants.TREE_NAME);
+        int num = 0;
+        for (GenTableColumn column : genTable.getColumns()) {
+            if (column.isList()) {
+                num++;
+                String columnName = column.getColumnName();
+                if (columnName.equals(treeName)) {
+                    break;
+                }
+            }
+        }
+        return num;
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml
new file mode 100644
index 0000000..5bd3dd6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml
@@ -0,0 +1,10 @@
+# 浠g爜鐢熸垚
+gen: 
+  # 浣滆��
+  author: ruoyi
+  # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+  packageName: com.ruoyi.system
+  # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸false
+  autoRemovePre: false
+  # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+  tablePrefix: sys_
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
new file mode 100644
index 0000000..3c49edb
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.generator.mapper.GenTableColumnMapper">
+
+    <resultMap type="com.ruoyi.generator.domain.GenTableColumn" id="GenTableColumnResult">
+    </resultMap>
+
+    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isMySql()">
+            select column_name,
+                   (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required,
+                   (case when column_key = 'PRI' then '1' else '0' end) as is_pk,
+                   ordinal_position as sort,
+                   column_comment,
+                   (case when extra = 'auto_increment' then '1' else '0' end) as is_increment,
+                   column_type
+            from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
+            order by ordinal_position
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isOracle()">
+            select lower(temp.column_name) as column_name,
+                    (case when (temp.nullable = 'N'  and  temp.constraint_type != 'P') then '1' else null end) as is_required,
+                    (case when temp.constraint_type = 'P' then '1' else '0' end) as is_pk,
+                    temp.column_id as sort,
+                    temp.comments as column_comment,
+                    (case when temp.constraint_type = 'P' then '1' else '0' end) as is_increment,
+                    lower(temp.data_type) as column_type
+            from (
+                select col.column_id, col.column_name,col.nullable, col.data_type, colc.comments, uc.constraint_type, row_number()
+                    over (partition by col.column_name order by uc.constraint_type desc) as row_flg
+                from user_tab_columns col
+                left join user_col_comments colc on colc.table_name = col.table_name and colc.column_name = col.column_name
+                left join user_cons_columns ucc on ucc.table_name = col.table_name and ucc.column_name = col.column_name
+                left join user_constraints uc on uc.constraint_name = ucc.constraint_name
+                where col.table_name = upper(#{tableName})
+            ) temp
+            WHERE temp.row_flg = 1
+            ORDER BY temp.column_id
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isPostgerSql()">
+            SELECT column_name, is_required, is_pk, sort, column_comment, is_increment, column_type
+            FROM (
+                SELECT c.relname AS table_name,
+                       a.attname AS column_name,
+                       d.description AS column_comment,
+                       CASE WHEN a.attnotnull AND con.conname IS NULL THEN 1 ELSE 0
+                       END AS is_required,
+                       CASE WHEN con.conname IS NOT NULL THEN 1 ELSE 0
+                       END AS is_pk,
+                       a.attnum AS sort,
+                       CASE WHEN "position"(pg_get_expr(ad.adbin, ad.adrelid),
+                           ((c.relname::text || '_'::text) || a.attname::text) || '_seq'::text) > 0 THEN 1 ELSE 0
+                       END AS is_increment,
+                       btrim(
+                           CASE WHEN t.typelem <![CDATA[ <> ]]> 0::oid AND t.typlen = '-1'::integer THEN 'ARRAY'::text ELSE
+                                CASE WHEN t.typtype = 'd'::"char" THEN format_type(t.typbasetype, NULL::integer)
+                                ELSE format_type(a.atttypid, NULL::integer) END
+                           END, '"'::text
+                       ) AS column_type
+                FROM pg_attribute a
+                    JOIN (pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid) ON a.attrelid = c.oid
+                    LEFT JOIN pg_description d ON d.objoid = c.oid AND a.attnum = d.objsubid
+                    LEFT JOIN pg_constraint con ON con.conrelid = c.oid AND (a.attnum = ANY (con.conkey))
+                    LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
+                    LEFT JOIN pg_type t ON a.atttypid = t.oid
+                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
+                    AND a.attnum > 0
+                    AND n.nspname = 'public'::name
+                ORDER BY c.relname, a.attnum
+            ) temp
+            WHERE table_name = (#{tableName})
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isSqlServer()">
+            SELECT
+                cast(A.NAME as nvarchar) as column_name,
+                cast(B.NAME as nvarchar) + (case when B.NAME = 'numeric' then '(' + cast(A.prec as nvarchar) + ',' + cast(A.scale as nvarchar) + ')' else '' end) as column_type,
+                cast(G.[VALUE] as nvarchar) as column_comment,
+                (SELECT 1 FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE Z WHERE TABLE_NAME = D.NAME and A.NAME = Z.column_name  ) as is_pk,
+                colorder as sort
+            FROM SYSCOLUMNS A
+                LEFT JOIN SYSTYPES B ON A.XTYPE = B.XUSERTYPE
+                INNER JOIN SYSOBJECTS D ON A.ID = D.ID AND D.XTYPE='U' AND D.NAME != 'DTPROPERTIES'
+                LEFT JOIN SYS.EXTENDED_PROPERTIES G ON A.ID = G.MAJOR_ID AND A.COLID = G.MINOR_ID
+                LEFT JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID AND F.MINOR_ID = 0
+            WHERE D.NAME = #{tableName}
+            ORDER BY A.COLORDER
+        </if>
+    </select>
+
+</mapper>
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
new file mode 100644
index 0000000..f23b000
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
+
+    <!-- 澶氱粨鏋勫祵濂楄嚜鍔ㄦ槧灏勯渶甯︿笂姣忎釜瀹炰綋鐨勪富閿甶d 鍚﹀垯鏄犲皠浼氬け璐� -->
+    <resultMap type="com.ruoyi.generator.domain.GenTable" id="GenTableResult">
+        <id property="tableId" column="table_id" />
+        <collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
+    </resultMap>
+
+    <resultMap type="com.ruoyi.generator.domain.GenTableColumn" id="GenTableColumnResult">
+        <id property="columnId" column="column_id"/>
+    </resultMap>
+
+    <select id="selectPageDbTableList" resultMap="GenTableResult">
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isMySql()">
+            select table_name, table_comment, create_time, update_time
+            from information_schema.tables
+            where table_schema = (select database())
+            AND table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%'
+            AND table_name NOT IN (select table_name from gen_table)
+            <if test="genTable.tableName != null and genTable.tableName != ''">
+                AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%'))
+            </if>
+            <if test="genTable.tableComment != null and genTable.tableComment != ''">
+                AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%'))
+            </if>
+            order by create_time desc
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isOracle()">
+            select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
+            from user_tables dt, user_tab_comments dtc, user_objects uo
+            where dt.table_name = dtc.table_name
+            and dt.table_name = uo.object_name
+            and uo.object_type = 'TABLE'
+            AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
+            AND lower(dt.table_name) NOT IN (select table_name from gen_table)
+            <if test="genTable.tableName != null and genTable.tableName != ''">
+                AND lower(dt.table_name) like lower(concat(concat('%', #{genTable.tableName}), '%'))
+            </if>
+            <if test="genTable.tableComment != null and genTable.tableComment != ''">
+                AND lower(dtc.comments) like lower(concat(concat('%', #{genTable.tableComment}), '%'))
+            </if>
+            order by create_time desc
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isPostgerSql()">
+            select table_name, table_comment, create_time, update_time
+            from (
+                SELECT c.relname AS table_name,
+                        obj_description(c.oid) AS table_comment,
+                        CURRENT_TIMESTAMP AS create_time,
+                        CURRENT_TIMESTAMP AS update_time
+                FROM pg_class c
+                    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
+                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
+                    AND c.relname != 'spatial_%'::text
+                    AND n.nspname = 'public'::name
+                    AND n.nspname <![CDATA[ <> ]]> ''::name
+            ) list_table
+            where table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%'
+            AND table_name NOT IN (select table_name from gen_table)
+            <if test="genTable.tableName != null and genTable.tableName != ''">
+                AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%'))
+            </if>
+            <if test="genTable.tableComment != null and genTable.tableComment != ''">
+                AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%'))
+            </if>
+            order by create_time desc
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isSqlServer()">
+            SELECT cast(D.NAME as nvarchar) as table_name,
+                   cast(F.VALUE as nvarchar) as table_comment,
+                   crdate as create_time,
+                   refdate as update_time
+            FROM SYSOBJECTS D
+                INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
+                    AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
+                    AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
+                    AND D.NAME NOT IN (select table_name from gen_table)
+            <if test="genTable.tableName != null and genTable.tableName != ''">
+                AND lower(D.NAME) like lower(concat(N'%', N'${genTable.tableName}', N'%'))
+            </if>
+            <if test="genTable.tableComment != null and genTable.tableComment != ''">
+                AND lower(CAST(F.VALUE AS nvarchar)) like lower(concat(N'%', N'${genTable.tableComment}', N'%'))
+            </if>
+            order by crdate desc
+        </if>
+    </select>
+
+    <select id="selectDbTableListByNames" resultMap="GenTableResult">
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isMySql()">
+            select table_name, table_comment, create_time, update_time from information_schema.tables
+            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
+            and table_name in
+            <foreach collection="array" item="name" open="(" separator="," close=")">
+                 #{name}
+            </foreach>
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isOracle()">
+            select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
+            from user_tables dt, user_tab_comments dtc, user_objects uo
+            where dt.table_name = dtc.table_name
+            and dt.table_name = uo.object_name
+            and uo.object_type = 'TABLE'
+            AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
+            AND dt.table_name NOT IN (select table_name from gen_table)
+            and lower(dt.table_name) in
+            <foreach collection="array" item="name" open="(" separator="," close=")">
+                #{name}
+            </foreach>
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isPostgerSql()">
+            select table_name, table_comment, create_time, update_time
+            from (
+                SELECT c.relname AS table_name,
+                        obj_description(c.oid) AS table_comment,
+                        CURRENT_TIMESTAMP AS create_time,
+                        CURRENT_TIMESTAMP AS update_time
+                FROM pg_class c
+                    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
+                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
+                    AND c.relname != 'spatial_%'::text
+                    AND n.nspname = 'public'::name
+                    AND n.nspname <![CDATA[ <> ]]> ''::name
+            ) list_table
+            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%'
+            and table_name in
+            <foreach collection="array" item="name" open="(" separator="," close=")">
+                #{name}
+            </foreach>
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isSqlServer()">
+            SELECT cast(D.NAME as nvarchar) as table_name,
+                   cast(F.VALUE as nvarchar) as table_comment,
+                   crdate as create_time,
+                   refdate as update_time
+            FROM SYSOBJECTS D
+                INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
+                    AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
+                    AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
+                    AND D.NAME in
+            <foreach collection="array" item="name" open="(" separator="," close=")">
+                #{name}
+            </foreach>
+        </if>
+    </select>
+
+    <select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isMySql()">
+            select table_name, table_comment, create_time, update_time from information_schema.tables
+            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
+            and table_name = #{tableName}
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isOracle()">
+            select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
+            from user_tables dt, user_tab_comments dtc, user_objects uo
+            where dt.table_name = dtc.table_name
+            and dt.table_name = uo.object_name
+            and uo.object_type = 'TABLE'
+            AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%'
+            AND dt.table_name NOT IN (select table_name from gen_table)
+            and lower(dt.table_name) = #{tableName}
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isPostgerSql()">
+            select table_name, table_comment, create_time, update_time
+            from (
+                SELECT c.relname AS table_name,
+                        obj_description(c.oid) AS table_comment,
+                        CURRENT_TIMESTAMP AS create_time,
+                        CURRENT_TIMESTAMP AS update_time
+                FROM pg_class c
+                    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
+                WHERE (c.relkind = ANY (ARRAY ['r'::"char", 'p'::"char"]))
+                    AND c.relname != 'spatial_%'::text
+                    AND n.nspname = 'public'::name
+                    AND n.nspname <![CDATA[ <> ]]> ''::name
+            ) list_table
+            where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%'
+            and table_name = #{tableName}
+        </if>
+        <if test="@com.ruoyi.common.mybatis.helper.DataBaseHelper@isSqlServer()">
+            SELECT cast(D.NAME as nvarchar) as table_name,
+                   cast(F.VALUE as nvarchar) as table_comment,
+                   crdate as create_time,
+                   refdate as update_time
+            FROM SYSOBJECTS D
+                INNER JOIN SYS.EXTENDED_PROPERTIES F ON D.ID = F.MAJOR_ID
+                    AND F.MINOR_ID = 0 AND D.XTYPE = 'U' AND D.NAME != 'DTPROPERTIES'
+                    AND D.NAME NOT LIKE 'xxl_job_%' AND D.NAME NOT LIKE 'gen_%'
+                    AND D.NAME = #{tableName}
+        </if>
+    </select>
+
+    <select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
+        SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
+               c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+        FROM gen_table t
+             LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+        where t.table_id = #{tableId} order by c.sort
+    </select>
+
+    <select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
+        SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
+               c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+        FROM gen_table t
+             LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+        where t.table_name = #{tableName} order by c.sort
+    </select>
+
+    <select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
+        SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
+               c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+        FROM gen_table t
+             LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+        order by c.sort
+    </select>
+
+</mapper>
diff --git a/ruoyi-generator/src/main/resources/mapper/package-info.md b/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/package-info.md
similarity index 100%
rename from ruoyi-generator/src/main/resources/mapper/package-info.md
rename to ruoyi-modules/ruoyi-generator/src/main/resources/mapper/package-info.md
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/bo.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
new file mode 100644
index 0000000..9ceb518
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
@@ -0,0 +1,60 @@
+package ${packageName}.domain.bo;
+
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+import java.util.Date;
+
+#foreach ($import in $importList)
+import ${import};
+#end
+#if($table.crud || $table.sub)
+import com.ruoyi.common.core.web.domain.BaseEntity;
+#elseif($table.tree)
+import com.ruoyi.common.core.web.domain.TreeEntity;
+#end
+
+/**
+ * ${functionName}涓氬姟瀵硅薄 ${tableName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+#if($table.crud || $table.sub)
+#set($Entity="BaseEntity")
+#elseif($table.tree)
+#set($Entity="TreeEntity<${ClassName}Bo>")
+#end
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ${ClassName}Bo extends ${Entity} {
+
+#foreach ($column in $columns)
+#if(!$table.isSuperColumn($column.javaField) && ($column.query || $column.isInsert || $column.isEdit))
+    /**
+     * $column.columnComment
+     */
+#if($column.isInsert && $column.isEdit)
+#set($Group="AddGroup.class, EditGroup.class")
+#elseif($column.isInsert)
+#set($Group="AddGroup.class")
+#elseif($column.isEdit)
+#set($Group="EditGroup.class")
+#end
+#if($column.isRequired == 1)
+#if($column.javaType == 'String')
+    @NotBlank(message = "$column.columnComment涓嶈兘涓虹┖", groups = { $Group })
+#else
+    @NotNull(message = "$column.columnComment涓嶈兘涓虹┖", groups = { $Group })
+#end
+#end
+    private $column.javaType $column.javaField;
+
+#end
+#end
+
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
new file mode 100644
index 0000000..14e00b1
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
@@ -0,0 +1,117 @@
+package ${packageName}.controller;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.ruoyi.common.web.annotation.RepeatSubmit;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import ${packageName}.domain.vo.${ClassName}Vo;
+import ${packageName}.domain.bo.${ClassName}Bo;
+import ${packageName}.service.I${ClassName}Service;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+#elseif($table.tree)
+#end
+
+/**
+ * ${functionName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/${moduleName}/${businessName}")
+public class ${ClassName}Controller extends BaseController {
+
+    private final I${ClassName}Service i${ClassName}Service;
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     */
+    @SaCheckPermission("${permissionPrefix}:list")
+    @GetMapping("/list")
+#if($table.crud || $table.sub)
+    public TableDataInfo<${ClassName}Vo> list(${ClassName}Bo bo, PageQuery pageQuery) {
+        return i${ClassName}Service.queryPageList(bo, pageQuery);
+    }
+#elseif($table.tree)
+    public R<List<${ClassName}Vo>> list(${ClassName}Bo bo) {
+        List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
+        return R.ok(list);
+    }
+#end
+
+    /**
+     * 瀵煎嚭${functionName}鍒楄〃
+     */
+    @SaCheckPermission("${permissionPrefix}:export")
+    @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(${ClassName}Bo bo, HttpServletResponse response) {
+        List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
+        ExcelUtil.exportExcel(list, "${functionName}", ${ClassName}Vo.class, response);
+    }
+
+    /**
+     * 鑾峰彇${functionName}璇︾粏淇℃伅
+     *
+     * @param ${pkColumn.javaField} 涓婚敭
+     */
+    @SaCheckPermission("${permissionPrefix}:query")
+    @GetMapping("/{${pkColumn.javaField}}")
+    public R<${ClassName}Vo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+                                     @PathVariable ${pkColumn.javaType} ${pkColumn.javaField}) {
+        return R.ok(i${ClassName}Service.queryById(${pkColumn.javaField}));
+    }
+
+    /**
+     * 鏂板${functionName}
+     */
+    @SaCheckPermission("${permissionPrefix}:add")
+    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) {
+        return toAjax(i${ClassName}Service.insertByBo(bo));
+    }
+
+    /**
+     * 淇敼${functionName}
+     */
+    @SaCheckPermission("${permissionPrefix}:edit")
+    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) {
+        return toAjax(i${ClassName}Service.updateByBo(bo));
+    }
+
+    /**
+     * 鍒犻櫎${functionName}
+     *
+     * @param ${pkColumn.javaField}s 涓婚敭涓�
+     */
+    @SaCheckPermission("${permissionPrefix}:remove")
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{${pkColumn.javaField}s}")
+    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                          @PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) {
+        return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
new file mode 100644
index 0000000..0ee607c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
@@ -0,0 +1,57 @@
+package ${packageName}.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.math.BigDecimal;
+
+#foreach ($import in $importList)
+import ${import};
+#end
+#if($table.crud || $table.sub)
+import com.ruoyi.common.core.web.domain.BaseEntity;
+#elseif($table.tree)
+import com.ruoyi.common.core.web.domain.TreeEntity;
+#end
+
+/**
+ * ${functionName}瀵硅薄 ${tableName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+#if($table.crud || $table.sub)
+    #set($Entity="BaseEntity")
+#elseif($table.tree)
+    #set($Entity="TreeEntity<${ClassName}>")
+#end
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("${tableName}")
+public class ${ClassName} extends ${Entity} {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+#foreach ($column in $columns)
+#if(!$table.isSuperColumn($column.javaField))
+    /**
+     * $column.columnComment
+     */
+#if($column.javaField=='delFlag')
+    @TableLogic
+#end
+#if($column.javaField=='version')
+    @Version
+#end
+#if($column.isPk==1)
+    @TableId(value = "$column.columnName")
+#end
+    private $column.javaType $column.javaField;
+#end
+#end
+
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
new file mode 100644
index 0000000..77fcb4c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
@@ -0,0 +1,15 @@
+package ${packageName}.mapper;
+
+import ${packageName}.domain.${ClassName};
+import ${packageName}.domain.vo.${ClassName}Vo;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * ${functionName}Mapper鎺ュ彛
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface ${ClassName}Mapper extends BaseMapperPlus<${ClassName}Mapper, ${ClassName}, ${ClassName}Vo> {
+
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/service.java.vm
new file mode 100644
index 0000000..6527c93
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/service.java.vm
@@ -0,0 +1,53 @@
+package ${packageName}.service;
+
+import ${packageName}.domain.${ClassName};
+import ${packageName}.domain.vo.${ClassName}Vo;
+import ${packageName}.domain.bo.${ClassName}Bo;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+#end
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * ${functionName}Service鎺ュ彛
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface I${ClassName}Service {
+
+    /**
+     * 鏌ヨ${functionName}
+     */
+    ${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField});
+
+#if($table.crud || $table.sub)
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     */
+    TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery);
+#end
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     */
+    List<${ClassName}Vo> queryList(${ClassName}Bo bo);
+
+    /**
+     * 鏂板${functionName}
+     */
+    Boolean insertByBo(${ClassName}Bo bo);
+
+    /**
+     * 淇敼${functionName}
+     */
+    Boolean updateByBo(${ClassName}Bo bo);
+
+    /**
+     * 鏍¢獙骞舵壒閲忓垹闄�${functionName}淇℃伅
+     */
+    Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid);
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
new file mode 100644
index 0000000..f568ff8
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
@@ -0,0 +1,134 @@
+package ${packageName}.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.ruoyi.common.core.utils.StringUtils;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+#end
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import ${packageName}.domain.bo.${ClassName}Bo;
+import ${packageName}.domain.vo.${ClassName}Vo;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.mapper.${ClassName}Mapper;
+import ${packageName}.service.I${ClassName}Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * ${functionName}Service涓氬姟灞傚鐞�
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@RequiredArgsConstructor
+@Service
+public class ${ClassName}ServiceImpl implements I${ClassName}Service {
+
+    private final ${ClassName}Mapper baseMapper;
+
+    /**
+     * 鏌ヨ${functionName}
+     */
+    @Override
+    public ${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField}){
+        return baseMapper.selectVoById(${pkColumn.javaField});
+    }
+
+#if($table.crud || $table.sub)
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     */
+    @Override
+    public TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
+        Page<${ClassName}Vo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+#end
+
+    /**
+     * 鏌ヨ${functionName}鍒楄〃
+     */
+    @Override
+    public List<${ClassName}Vo> queryList(${ClassName}Bo bo) {
+        LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<${ClassName}> buildQueryWrapper(${ClassName}Bo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<${ClassName}> lqw = Wrappers.lambdaQuery();
+#foreach($column in $columns)
+#if($column.query)
+#set($queryType=$column.queryType)
+#set($javaField=$column.javaField)
+#set($javaType=$column.javaType)
+#set($columnName=$column.columnName)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($mpMethod=$column.queryType.toLowerCase())
+#if($queryType != 'BETWEEN')
+#if($javaType == 'String')
+#set($condition='StringUtils.isNotBlank(bo.get'+$AttrName+'())')
+#else
+#set($condition='bo.get'+$AttrName+'() != null')
+#end
+        lqw.$mpMethod($condition, ${ClassName}::get$AttrName, bo.get$AttrName());
+#else
+        lqw.between(params.get("begin$AttrName") != null && params.get("end$AttrName") != null,
+            ${ClassName}::get$AttrName ,params.get("begin$AttrName"), params.get("end$AttrName"));
+#end
+#end
+#end
+        return lqw;
+    }
+
+    /**
+     * 鏂板${functionName}
+     */
+    @Override
+    public Boolean insertByBo(${ClassName}Bo bo) {
+        ${ClassName} add = BeanUtil.toBean(bo, ${ClassName}.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+#set($pk=$pkColumn.javaField.substring(0,1).toUpperCase() + ${pkColumn.javaField.substring(1)})
+        if (flag) {
+            bo.set$pk(add.get$pk());
+        }
+        return flag;
+    }
+
+    /**
+     * 淇敼${functionName}
+     */
+    @Override
+    public Boolean updateByBo(${ClassName}Bo bo) {
+        ${ClassName} update = BeanUtil.toBean(bo, ${ClassName}.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+     */
+    private void validEntityBeforeSave(${ClassName} entity){
+        //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎${functionName}
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+        }
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+}
diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm
new file mode 100644
index 0000000..327c46c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm
@@ -0,0 +1,56 @@
+package ${packageName}.domain.vo;
+
+#foreach ($import in $importList)
+import ${import};
+#end
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * ${functionName}瑙嗗浘瀵硅薄 ${tableName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class ${ClassName}Vo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+#foreach ($column in $columns)
+#if($column.isList)
+    /**
+     * $column.columnComment
+     */
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if(${column.dictType} && ${column.dictType} != '')
+    @ExcelProperty(value = "${comment}", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "${column.dictType}")
+#elseif($parentheseIndex != -1)
+    @ExcelProperty(value = "${comment}", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "$column.readConverterExp()")
+#else
+    @ExcelProperty(value = "${comment}")
+#end
+    private $column.javaType $column.javaField;
+
+#end
+#end
+
+}
diff --git a/ruoyi-generator/src/main/resources/vm/js/api.js.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/js/api.js.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/js/api.js.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/js/api.js.vm
diff --git a/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm
diff --git a/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm
diff --git a/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/sql/sql.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm
diff --git a/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm
diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt
diff --git a/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi-modules/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
similarity index 100%
rename from ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
rename to ruoyi-modules/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
diff --git a/ruoyi-modules/ruoyi-job/pom.xml b/ruoyi-modules/ruoyi-job/pom.xml
new file mode 100644
index 0000000..e886a29
--- /dev/null
+++ b/ruoyi-modules/ruoyi-job/pom.xml
@@ -0,0 +1,36 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-modules</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>ruoyi-job</artifactId>
+
+    <description>
+        浠诲姟璋冨害
+    </description>
+
+    <dependencies>
+
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <!-- xxl-job-core -->
+        <dependency>
+            <groupId>com.xuxueli</groupId>
+            <artifactId>xxl-job-core</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>
+
diff --git a/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java
similarity index 100%
rename from ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java
rename to ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java
diff --git a/ruoyi-job/src/main/java/com/ruoyi/job/config/properties/XxlJobProperties.java b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/config/properties/XxlJobProperties.java
similarity index 100%
rename from ruoyi-job/src/main/java/com/ruoyi/job/config/properties/XxlJobProperties.java
rename to ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/config/properties/XxlJobProperties.java
diff --git a/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java
similarity index 100%
rename from ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java
rename to ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java
diff --git a/ruoyi-modules/ruoyi-system/pom.xml b/ruoyi-modules/ruoyi-system/pom.xml
new file mode 100644
index 0000000..690d793
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/pom.xml
@@ -0,0 +1,80 @@
+<?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.ruoyi</groupId>
+        <artifactId>ruoyi-modules</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-system</artifactId>
+
+    <description>
+        system绯荤粺妯″潡
+    </description>
+
+    <dependencies>
+        <!-- 閫氱敤宸ュ叿-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-mybatis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-dict</artifactId>
+        </dependency>
+
+        <!-- OSS鍔熻兘妯″潡 -->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-oss</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-log</artifactId>
+        </dependency>
+
+        <!-- excel-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-excel</artifactId>
+        </dependency>
+
+        <!-- SMS鍔熻兘妯″潡 -->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-sms</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-satoken</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-security</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-idempotent</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java
new file mode 100644
index 0000000..84f17bc
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java
@@ -0,0 +1,169 @@
+package com.ruoyi.system.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.collection.CollUtil;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.system.domain.SysCache;
+import lombok.RequiredArgsConstructor;
+import org.redisson.spring.data.connection.RedissonConnectionFactory;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 缂撳瓨鐩戞帶
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor/cache")
+public class CacheController {
+
+    private final RedissonConnectionFactory connectionFactory;
+
+    private final static List<SysCache> CACHES = new ArrayList<>();
+
+    static {
+        CACHES.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "鐢ㄦ埛淇℃伅"));
+        CACHES.add(new SysCache(CacheConstants.ONLINE_TOKEN_KEY, "鍦ㄧ嚎鐢ㄦ埛"));
+        CACHES.add(new SysCache(CacheNames.SYS_CONFIG, "閰嶇疆淇℃伅"));
+        CACHES.add(new SysCache(CacheNames.SYS_DICT, "鏁版嵁瀛楀吀"));
+        CACHES.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "楠岃瘉鐮�"));
+        CACHES.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "闃查噸鎻愪氦"));
+        CACHES.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "闄愭祦澶勭悊"));
+        CACHES.add(new SysCache(CacheNames.SYS_OSS_CONFIG, "OSS閰嶇疆"));
+        CACHES.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "瀵嗙爜閿欒娆℃暟"));
+    }
+
+    /**
+     * 鑾峰彇缂撳瓨鐩戞帶鍒楄〃
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @GetMapping()
+    public R<Map<String, Object>> getInfo() throws Exception {
+        RedisConnection connection = connectionFactory.getConnection();
+        Properties info = connection.commands().info();
+        Properties commandStats = connection.commands().info("commandstats");
+        Long dbSize = connection.commands().dbSize();
+
+        Map<String, Object> result = new HashMap<>(3);
+        result.put("info", info);
+        result.put("dbSize", dbSize);
+
+        List<Map<String, String>> pieList = new ArrayList<>();
+        if (commandStats != null) {
+            commandStats.stringPropertyNames().forEach(key -> {
+                Map<String, String> data = new HashMap<>(2);
+                String property = commandStats.getProperty(key);
+                data.put("name", StringUtils.removeStart(key, "cmdstat_"));
+                data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
+                pieList.add(data);
+            });
+        }
+        result.put("commandStats", pieList);
+        return R.ok(result);
+    }
+
+    /**
+     * 鑾峰彇缂撳瓨鐩戞帶缂撳瓨鍚嶅垪琛�
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @GetMapping("/getNames")
+    public R<List<SysCache>> cache() {
+        return R.ok(CACHES);
+    }
+
+    /**
+     * 鑾峰彇缂撳瓨鐩戞帶Key鍒楄〃
+     *
+     * @param cacheName 缂撳瓨鍚�
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @GetMapping("/getKeys/{cacheName}")
+    public R<Collection<String>> getCacheKeys(@PathVariable String cacheName) {
+        Collection<String> cacheKeys = new HashSet<>(0);
+        if (isCacheNames(cacheName)) {
+            Set<Object> keys = CacheUtils.keys(cacheName);
+            if (CollUtil.isNotEmpty(keys)) {
+                cacheKeys = keys.stream().map(Object::toString).collect(Collectors.toList());
+            }
+        } else {
+            cacheKeys = RedisUtils.keys(cacheName + "*");
+        }
+        return R.ok(cacheKeys);
+    }
+
+    /**
+     * 鑾峰彇缂撳瓨鐩戞帶缂撳瓨鍊艰鎯�
+     *
+     * @param cacheName 缂撳瓨鍚�
+     * @param cacheKey  缂撳瓨key
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @GetMapping("/getValue/{cacheName}/{cacheKey}")
+    public R<SysCache> getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) {
+        Object cacheValue;
+        if (isCacheNames(cacheName)) {
+            cacheValue = CacheUtils.get(cacheName, cacheKey);
+        } else {
+            cacheValue = RedisUtils.getCacheObject(cacheKey);
+        }
+        SysCache sysCache = new SysCache(cacheName, cacheKey, JsonUtils.toJsonString(cacheValue));
+        return R.ok(sysCache);
+    }
+
+    /**
+     * 娓呯悊缂撳瓨鐩戞帶缂撳瓨鍚�
+     *
+     * @param cacheName 缂撳瓨鍚�
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @DeleteMapping("/clearCacheName/{cacheName}")
+    public R<Void> clearCacheName(@PathVariable String cacheName) {
+        if (isCacheNames(cacheName)) {
+            CacheUtils.clear(cacheName);
+        } else {
+            RedisUtils.deleteKeys(cacheName + "*");
+        }
+        return R.ok();
+    }
+
+    /**
+     * 娓呯悊缂撳瓨鐩戞帶Key
+     *
+     * @param cacheKey key鍚�
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @DeleteMapping("/clearCacheKey/{cacheName}/{cacheKey}")
+    public R<Void> clearCacheKey(@PathVariable String cacheName, @PathVariable String cacheKey) {
+        if (isCacheNames(cacheName)) {
+            CacheUtils.evict(cacheName, cacheKey);
+        } else {
+            RedisUtils.deleteObject(cacheKey);
+        }
+        return R.ok();
+    }
+
+    /**
+     * 娓呯悊鍏ㄩ儴缂撳瓨鐩戞帶
+     */
+    @SaCheckPermission("monitor:cache:list")
+    @DeleteMapping("/clearCacheAll")
+    public R<Void> clearCacheAll() {
+        RedisUtils.deleteKeys("*");
+        return R.ok();
+    }
+
+    private boolean isCacheNames(String cacheName) {
+        return !StringUtils.contains(cacheName, ":");
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java
new file mode 100644
index 0000000..e302c99
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java
@@ -0,0 +1,88 @@
+package com.ruoyi.system.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.service.ISysLogininforService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 绯荤粺璁块棶璁板綍
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor/logininfor")
+public class SysLogininforController extends BaseController {
+
+    private final ISysLogininforService logininforService;
+
+    /**
+     * 鑾峰彇绯荤粺璁块棶璁板綍鍒楄〃
+     */
+    @SaCheckPermission("monitor:logininfor:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysLogininfor> list(SysLogininfor logininfor, PageQuery pageQuery) {
+        return logininforService.selectPageLogininforList(logininfor, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭绯荤粺璁块棶璁板綍鍒楄〃
+     */
+    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("monitor:logininfor:export")
+    @PostMapping("/export")
+    public void export(SysLogininfor logininfor, HttpServletResponse response) {
+        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+        ExcelUtil.exportExcel(list, "鐧诲綍鏃ュ織", SysLogininfor.class, response);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鐧诲綍鏃ュ織
+     * @param infoIds 鏃ュ織ids
+     */
+    @SaCheckPermission("monitor:logininfor:remove")
+    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{infoIds}")
+    public R<Void> remove(@PathVariable Long[] infoIds) {
+        return toAjax(logininforService.deleteLogininforByIds(infoIds));
+    }
+
+    /**
+     * 娓呯悊绯荤粺璁块棶璁板綍
+     */
+    @SaCheckPermission("monitor:logininfor:remove")
+    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/clean")
+    public R<Void> clean() {
+        logininforService.cleanLogininfor();
+        return R.ok();
+    }
+
+    @SaCheckPermission("monitor:logininfor:unlock")
+    @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
+    @GetMapping("/unlock/{userName}")
+    public R<Void> unlock(@PathVariable("userName") String userName) {
+        String loginName = CacheConstants.PWD_ERR_CNT_KEY + userName;
+        if (RedisUtils.hasKey(loginName)) {
+            RedisUtils.deleteObject(loginName);
+        }
+        return R.ok();
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java
new file mode 100644
index 0000000..2ad5a3f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java
@@ -0,0 +1,74 @@
+package com.ruoyi.system.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.service.ISysOperLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor/operlog")
+public class SysOperlogController extends BaseController {
+
+    private final ISysOperLogService operLogService;
+
+    /**
+     * 鑾峰彇鎿嶄綔鏃ュ織璁板綍鍒楄〃
+     */
+    @SaCheckPermission("monitor:operlog:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysOperLog> list(SysOperLog operLog, PageQuery pageQuery) {
+        return operLogService.selectPageOperLogList(operLog, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭鎿嶄綔鏃ュ織璁板綍鍒楄〃
+     */
+    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("monitor:operlog:export")
+    @PostMapping("/export")
+    public void export(SysOperLog operLog, HttpServletResponse response) {
+        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+        ExcelUtil.exportExcel(list, "鎿嶄綔鏃ュ織", SysOperLog.class, response);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鎿嶄綔鏃ュ織璁板綍
+     * @param operIds 鏃ュ織ids
+     */
+    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.DELETE)
+    @SaCheckPermission("monitor:operlog:remove")
+    @DeleteMapping("/{operIds}")
+    public R<Void> remove(@PathVariable Long[] operIds) {
+        return toAjax(operLogService.deleteOperLogByIds(operIds));
+    }
+
+    /**
+     * 娓呯悊鎿嶄綔鏃ュ織璁板綍
+     */
+    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.CLEAN)
+    @SaCheckPermission("monitor:operlog:remove")
+    @DeleteMapping("/clean")
+    public R<Void> clean() {
+        operLogService.cleanOperLog();
+        return R.ok();
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java
new file mode 100644
index 0000000..db741b1
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java
@@ -0,0 +1,90 @@
+package com.ruoyi.system.controller.monitor;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.system.domain.SysUserOnline;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛鐩戞帶
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/monitor/online")
+public class SysUserOnlineController extends BaseController {
+
+    /**
+     * 鑾峰彇鍦ㄧ嚎鐢ㄦ埛鐩戞帶鍒楄〃
+     *
+     * @param ipaddr   IP鍦板潃
+     * @param userName 鐢ㄦ埛鍚�
+     */
+    @SaCheckPermission("monitor:online:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysUserOnline> list(String ipaddr, String userName) {
+        // 鑾峰彇鎵�鏈夋湭杩囨湡鐨� token
+        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
+        List<UserOnlineDTO> userOnlineDTOList = new ArrayList<>();
+        for (String key : keys) {
+            String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, "");
+            // 濡傛灉宸茬粡杩囨湡鍒欒烦杩�
+            if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < -1) {
+                continue;
+            }
+            userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token));
+        }
+        if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
+            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
+                StringUtils.equals(ipaddr, userOnline.getIpaddr()) &&
+                    StringUtils.equals(userName, userOnline.getUserName())
+            );
+        } else if (StringUtils.isNotEmpty(ipaddr)) {
+            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
+                StringUtils.equals(ipaddr, userOnline.getIpaddr())
+            );
+        } else if (StringUtils.isNotEmpty(userName)) {
+            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
+                StringUtils.equals(userName, userOnline.getUserName())
+            );
+        }
+        Collections.reverse(userOnlineDTOList);
+        userOnlineDTOList.removeAll(Collections.singleton(null));
+        List<SysUserOnline> userOnlineList = BeanUtil.copyToList(userOnlineDTOList, SysUserOnline.class);
+        return TableDataInfo.build(userOnlineList);
+    }
+
+    /**
+     * 寮洪��鐢ㄦ埛
+     *
+     * @param tokenId token鍊�
+     */
+    @SaCheckPermission("monitor:online:forceLogout")
+    @Log(title = "鍦ㄧ嚎鐢ㄦ埛", businessType = BusinessType.FORCE)
+    @DeleteMapping("/{tokenId}")
+    public R<Void> forceLogout(@PathVariable String tokenId) {
+        try {
+            StpUtil.kickoutByTokenValue(tokenId);
+        } catch (NotLoginException ignored) {
+        }
+        return R.ok();
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java
new file mode 100644
index 0000000..d558e52
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java
@@ -0,0 +1,137 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.domain.SysConfig;
+import com.ruoyi.system.service.ISysConfigService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/config")
+public class SysConfigController extends BaseController {
+
+    private final ISysConfigService configService;
+
+    /**
+     * 鑾峰彇鍙傛暟閰嶇疆鍒楄〃
+     */
+    @SaCheckPermission("system:config:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysConfig> list(SysConfig config, PageQuery pageQuery) {
+        return configService.selectPageConfigList(config, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭鍙傛暟閰嶇疆鍒楄〃
+     */
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("system:config:export")
+    @PostMapping("/export")
+    public void export(SysConfig config, HttpServletResponse response) {
+        List<SysConfig> list = configService.selectConfigList(config);
+        ExcelUtil.exportExcel(list, "鍙傛暟鏁版嵁", SysConfig.class, response);
+    }
+
+    /**
+     * 鏍规嵁鍙傛暟缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param configId 鍙傛暟ID
+     */
+    @SaCheckPermission("system:config:query")
+    @GetMapping(value = "/{configId}")
+    public R<SysConfig> getInfo(@PathVariable Long configId) {
+        return R.ok(configService.selectConfigById(configId));
+    }
+
+    /**
+     * 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
+     *
+     * @param configKey 鍙傛暟Key
+     */
+    @GetMapping(value = "/configKey/{configKey}")
+    public R<Void> getConfigKey(@PathVariable String configKey) {
+        return R.ok(configService.selectConfigByKey(configKey));
+    }
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     */
+    @SaCheckPermission("system:config:add")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysConfig config) {
+        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
+            return R.fail("鏂板鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+        }
+        configService.insertConfig(config);
+        return R.ok();
+    }
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     */
+    @SaCheckPermission("system:config:edit")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysConfig config) {
+        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
+            return R.fail("淇敼鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+        }
+        configService.updateConfig(config);
+        return R.ok();
+    }
+
+    /**
+     * 鏍规嵁鍙傛暟閿悕淇敼鍙傛暟閰嶇疆
+     */
+    @SaCheckPermission("system:config:edit")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/updateByKey")
+    public R<Void> updateByKey(@RequestBody SysConfig config) {
+        configService.updateConfig(config);
+        return R.ok();
+    }
+
+    /**
+     * 鍒犻櫎鍙傛暟閰嶇疆
+     *
+     * @param configIds 鍙傛暟ID涓�
+     */
+    @SaCheckPermission("system:config:remove")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{configIds}")
+    public R<Void> remove(@PathVariable Long[] configIds) {
+        configService.deleteConfigByIds(configIds);
+        return R.ok();
+    }
+
+    /**
+     * 鍒锋柊鍙傛暟缂撳瓨
+     */
+    @SaCheckPermission("system:config:remove")
+    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/refreshCache")
+    public R<Void> refreshCache() {
+        configService.resetConfigCache();
+        return R.ok();
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java
new file mode 100644
index 0000000..18c2b0e
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java
@@ -0,0 +1,119 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.ArrayUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.domain.SysDept;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.system.service.ISysDeptService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 閮ㄩ棬淇℃伅
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/dept")
+public class SysDeptController extends BaseController {
+
+    private final ISysDeptService deptService;
+
+    /**
+     * 鑾峰彇閮ㄩ棬鍒楄〃
+     */
+    @SaCheckPermission("system:dept:list")
+    @GetMapping("/list")
+    public R<List<SysDept>> list(SysDept dept) {
+        List<SysDept> depts = deptService.selectDeptList(dept);
+        return R.ok(depts);
+    }
+
+    /**
+     * 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
+     *
+     * @param deptId 閮ㄩ棬ID
+     */
+    @SaCheckPermission("system:dept:list")
+    @GetMapping("/list/exclude/{deptId}")
+    public R<List<SysDept>> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
+        List<SysDept> depts = deptService.selectDeptList(new SysDept());
+        depts.removeIf(d -> d.getDeptId().equals(deptId)
+            || ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
+        return R.ok(depts);
+    }
+
+    /**
+     * 鏍规嵁閮ㄩ棬缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param deptId 閮ㄩ棬ID
+     */
+    @SaCheckPermission("system:dept:query")
+    @GetMapping(value = "/{deptId}")
+    public R<SysDept> getInfo(@PathVariable Long deptId) {
+        deptService.checkDeptDataScope(deptId);
+        return R.ok(deptService.selectDeptById(deptId));
+    }
+
+    /**
+     * 鏂板閮ㄩ棬
+     */
+    @SaCheckPermission("system:dept:add")
+    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysDept dept) {
+        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
+            return R.fail("鏂板閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+        }
+        return toAjax(deptService.insertDept(dept));
+    }
+
+    /**
+     * 淇敼閮ㄩ棬
+     */
+    @SaCheckPermission("system:dept:edit")
+    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysDept dept) {
+        Long deptId = dept.getDeptId();
+        deptService.checkDeptDataScope(deptId);
+        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
+            return R.fail("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+        } else if (dept.getParentId().equals(deptId)) {
+            return R.fail("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛屼笂绾ч儴闂ㄤ笉鑳芥槸鑷繁");
+        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
+            && deptService.selectNormalChildrenDeptById(deptId) > 0) {
+            return R.fail("璇ラ儴闂ㄥ寘鍚湭鍋滅敤鐨勫瓙閮ㄩ棬锛�");
+        }
+        return toAjax(deptService.updateDept(dept));
+    }
+
+    /**
+     * 鍒犻櫎閮ㄩ棬
+     *
+     * @param deptId 閮ㄩ棬ID
+     */
+    @SaCheckPermission("system:dept:remove")
+    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{deptId}")
+    public R<Void> remove(@PathVariable Long deptId) {
+        if (deptService.hasChildByDeptId(deptId)) {
+            return R.warn("瀛樺湪涓嬬骇閮ㄩ棬,涓嶅厑璁稿垹闄�");
+        }
+        if (deptService.checkDeptExistUser(deptId)) {
+            return R.warn("閮ㄩ棬瀛樺湪鐢ㄦ埛,涓嶅厑璁稿垹闄�");
+        }
+        deptService.checkDeptDataScope(deptId);
+        return toAjax(deptService.deleteDeptById(deptId));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java
new file mode 100644
index 0000000..2fd9259
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java
@@ -0,0 +1,116 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.domain.SysDictData;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.service.ISysDictDataService;
+import com.ruoyi.system.service.ISysDictTypeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/dict/data")
+public class SysDictDataController extends BaseController {
+
+    private final ISysDictDataService dictDataService;
+    private final ISysDictTypeService dictTypeService;
+
+    /**
+     * 鏌ヨ瀛楀吀鏁版嵁鍒楄〃
+     */
+    @SaCheckPermission("system:dict:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysDictData> list(SysDictData dictData, PageQuery pageQuery) {
+        return dictDataService.selectPageDictDataList(dictData, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭瀛楀吀鏁版嵁鍒楄〃
+     */
+    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("system:dict:export")
+    @PostMapping("/export")
+    public void export(SysDictData dictData, HttpServletResponse response) {
+        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+        ExcelUtil.exportExcel(list, "瀛楀吀鏁版嵁", SysDictData.class, response);
+    }
+
+    /**
+     * 鏌ヨ瀛楀吀鏁版嵁璇︾粏
+     *
+     * @param dictCode 瀛楀吀code
+     */
+    @SaCheckPermission("system:dict:query")
+    @GetMapping(value = "/{dictCode}")
+    public R<SysDictData> getInfo(@PathVariable Long dictCode) {
+        return R.ok(dictDataService.selectDictDataById(dictCode));
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     */
+    @GetMapping(value = "/type/{dictType}")
+    public R<List<SysDictData>> dictType(@PathVariable String dictType) {
+        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
+        if (ObjectUtil.isNull(data)) {
+            data = new ArrayList<>();
+        }
+        return R.ok(data);
+    }
+
+    /**
+     * 鏂板瀛楀吀绫诲瀷
+     */
+    @SaCheckPermission("system:dict:add")
+    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysDictData dict) {
+        dictDataService.insertDictData(dict);
+        return R.ok();
+    }
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀绫诲瀷
+     */
+    @SaCheckPermission("system:dict:edit")
+    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysDictData dict) {
+        dictDataService.updateDictData(dict);
+        return R.ok();
+    }
+
+    /**
+     * 鍒犻櫎瀛楀吀绫诲瀷
+     *
+     * @param dictCodes 瀛楀吀code涓�
+     */
+    @SaCheckPermission("system:dict:remove")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{dictCodes}")
+    public R<Void> remove(@PathVariable Long[] dictCodes) {
+        dictDataService.deleteDictDataByIds(dictCodes);
+        return R.ok();
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java
new file mode 100644
index 0000000..31c76cf
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java
@@ -0,0 +1,125 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.domain.SysDictType;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.service.ISysDictTypeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/dict/type")
+public class SysDictTypeController extends BaseController {
+
+    private final ISysDictTypeService dictTypeService;
+
+    /**
+     * 鏌ヨ瀛楀吀绫诲瀷鍒楄〃
+     */
+    @SaCheckPermission("system:dict:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysDictType> list(SysDictType dictType, PageQuery pageQuery) {
+        return dictTypeService.selectPageDictTypeList(dictType, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭瀛楀吀绫诲瀷鍒楄〃
+     */
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("system:dict:export")
+    @PostMapping("/export")
+    public void export(SysDictType dictType, HttpServletResponse response) {
+        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+        ExcelUtil.exportExcel(list, "瀛楀吀绫诲瀷", SysDictType.class, response);
+    }
+
+    /**
+     * 鏌ヨ瀛楀吀绫诲瀷璇︾粏
+     *
+     * @param dictId 瀛楀吀ID
+     */
+    @SaCheckPermission("system:dict:query")
+    @GetMapping(value = "/{dictId}")
+    public R<SysDictType> getInfo(@PathVariable Long dictId) {
+        return R.ok(dictTypeService.selectDictTypeById(dictId));
+    }
+
+    /**
+     * 鏂板瀛楀吀绫诲瀷
+     */
+    @SaCheckPermission("system:dict:add")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysDictType dict) {
+        if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) {
+            return R.fail("鏂板瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+        }
+        dictTypeService.insertDictType(dict);
+        return R.ok();
+    }
+
+    /**
+     * 淇敼瀛楀吀绫诲瀷
+     */
+    @SaCheckPermission("system:dict:edit")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysDictType dict) {
+        if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) {
+            return R.fail("淇敼瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+        }
+        dictTypeService.updateDictType(dict);
+        return R.ok();
+    }
+
+    /**
+     * 鍒犻櫎瀛楀吀绫诲瀷
+     *
+     * @param dictIds 瀛楀吀ID涓�
+     */
+    @SaCheckPermission("system:dict:remove")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{dictIds}")
+    public R<Void> remove(@PathVariable Long[] dictIds) {
+        dictTypeService.deleteDictTypeByIds(dictIds);
+        return R.ok();
+    }
+
+    /**
+     * 鍒锋柊瀛楀吀缂撳瓨
+     */
+    @SaCheckPermission("system:dict:remove")
+    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
+    @DeleteMapping("/refreshCache")
+    public R<Void> refreshCache() {
+        dictTypeService.resetDictCache();
+        return R.ok();
+    }
+
+    /**
+     * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
+     */
+    @GetMapping("/optionselect")
+    public R<List<SysDictType>> optionselect() {
+        List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
+        return R.ok(dictTypes);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
new file mode 100644
index 0000000..58ffeb1
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
@@ -0,0 +1,128 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.lang.tree.Tree;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.system.domain.SysMenu;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.system.service.ISysMenuService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鑿滃崟淇℃伅
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/menu")
+public class SysMenuController extends BaseController {
+
+    private final ISysMenuService menuService;
+
+    /**
+     * 鑾峰彇鑿滃崟鍒楄〃
+     */
+    @SaCheckPermission("system:menu:list")
+    @GetMapping("/list")
+    public R<List<SysMenu>> list(SysMenu menu) {
+        List<SysMenu> menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
+        return R.ok(menus);
+    }
+
+    /**
+     * 鏍规嵁鑿滃崟缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param menuId 鑿滃崟ID
+     */
+    @SaCheckPermission("system:menu:query")
+    @GetMapping(value = "/{menuId}")
+    public R<SysMenu> getInfo(@PathVariable Long menuId) {
+        return R.ok(menuService.selectMenuById(menuId));
+    }
+
+    /**
+     * 鑾峰彇鑿滃崟涓嬫媺鏍戝垪琛�
+     */
+    @GetMapping("/treeselect")
+    public R<List<Tree<Long>>> treeselect(SysMenu menu) {
+        List<SysMenu> menus = menuService.selectMenuList(menu, LoginHelper.getUserId());
+        return R.ok(menuService.buildMenuTreeSelect(menus));
+    }
+
+    /**
+     * 鍔犺浇瀵瑰簲瑙掕壊鑿滃崟鍒楄〃鏍�
+     *
+     * @param roleId 瑙掕壊ID
+     */
+    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
+    public R<Map<String, Object>> roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
+        List<SysMenu> menus = menuService.selectMenuList(LoginHelper.getUserId());
+        Map<String, Object> ajax = new HashMap<>();
+        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
+        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
+        return R.ok(ajax);
+    }
+
+    /**
+     * 鏂板鑿滃崟
+     */
+    @SaCheckPermission("system:menu:add")
+    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysMenu menu) {
+        if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
+            return R.fail("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+        } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
+            return R.fail("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+        }
+        return toAjax(menuService.insertMenu(menu));
+    }
+
+    /**
+     * 淇敼鑿滃崟
+     */
+    @SaCheckPermission("system:menu:edit")
+    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysMenu menu) {
+        if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
+            return R.fail("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+        } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
+            return R.fail("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+        } else if (menu.getMenuId().equals(menu.getParentId())) {
+            return R.fail("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屼笂绾ц彍鍗曚笉鑳介�夋嫨鑷繁");
+        }
+        return toAjax(menuService.updateMenu(menu));
+    }
+
+    /**
+     * 鍒犻櫎鑿滃崟
+     *
+     * @param menuId 鑿滃崟ID
+     */
+    @SaCheckPermission("system:menu:remove")
+    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{menuId}")
+    public R<Void> remove(@PathVariable("menuId") Long menuId) {
+        if (menuService.hasChildByMenuId(menuId)) {
+            return R.warn("瀛樺湪瀛愯彍鍗�,涓嶅厑璁稿垹闄�");
+        }
+        if (menuService.checkMenuExistRole(menuId)) {
+            return R.warn("鑿滃崟宸插垎閰�,涓嶅厑璁稿垹闄�");
+        }
+        return toAjax(menuService.deleteMenuById(menuId));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java
new file mode 100644
index 0000000..5393243
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java
@@ -0,0 +1,80 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.system.domain.SysNotice;
+import com.ruoyi.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 鍏憡 淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/notice")
+public class SysNoticeController extends BaseController {
+
+    private final ISysNoticeService noticeService;
+
+    /**
+     * 鑾峰彇閫氱煡鍏憡鍒楄〃
+     */
+    @SaCheckPermission("system:notice:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysNotice> list(SysNotice notice, PageQuery pageQuery) {
+        return noticeService.selectPageNoticeList(notice, pageQuery);
+    }
+
+    /**
+     * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param noticeId 鍏憡ID
+     */
+    @SaCheckPermission("system:notice:query")
+    @GetMapping(value = "/{noticeId}")
+    public R<SysNotice> getInfo(@PathVariable Long noticeId) {
+        return R.ok(noticeService.selectNoticeById(noticeId));
+    }
+
+    /**
+     * 鏂板閫氱煡鍏憡
+     */
+    @SaCheckPermission("system:notice:add")
+    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysNotice notice) {
+        return toAjax(noticeService.insertNotice(notice));
+    }
+
+    /**
+     * 淇敼閫氱煡鍏憡
+     */
+    @SaCheckPermission("system:notice:edit")
+    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysNotice notice) {
+        return toAjax(noticeService.updateNotice(notice));
+    }
+
+    /**
+     * 鍒犻櫎閫氱煡鍏憡
+     *
+     * @param noticeIds 鍏憡ID涓�
+     */
+    @SaCheckPermission("system:notice:remove")
+    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{noticeIds}")
+    public R<Void> remove(@PathVariable Long[] noticeIds) {
+        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java
new file mode 100644
index 0000000..c7ac90f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java
@@ -0,0 +1,105 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.idempotent.annotation.RepeatSubmit;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.system.domain.bo.SysOssConfigBo;
+import com.ruoyi.system.domain.vo.SysOssConfigVo;
+import com.ruoyi.system.service.ISysOssConfigService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import java.util.Arrays;
+
+/**
+ * 瀵硅薄瀛樺偍閰嶇疆
+ *
+ * @author Lion Li
+ * @author 瀛よ垷鐑熼洦
+ * @date 2021-08-13
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/oss/config")
+public class SysOssConfigController extends BaseController {
+
+    private final ISysOssConfigService iSysOssConfigService;
+
+    /**
+     * 鏌ヨ瀵硅薄瀛樺偍閰嶇疆鍒楄〃
+     */
+    @SaCheckPermission("system:oss:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
+        return iSysOssConfigService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄瀛樺偍閰嶇疆璇︾粏淇℃伅
+     *
+     * @param ossConfigId OSS閰嶇疆ID
+     */
+    @SaCheckPermission("system:oss:query")
+    @GetMapping("/{ossConfigId}")
+    public R<SysOssConfigVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+                                     @PathVariable Long ossConfigId) {
+        return R.ok(iSysOssConfigService.queryById(ossConfigId));
+    }
+
+    /**
+     * 鏂板瀵硅薄瀛樺偍閰嶇疆
+     */
+    @SaCheckPermission("system:oss:add")
+    @Log(title = "瀵硅薄瀛樺偍閰嶇疆", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
+        return toAjax(iSysOssConfigService.insertByBo(bo));
+    }
+
+    /**
+     * 淇敼瀵硅薄瀛樺偍閰嶇疆
+     */
+    @SaCheckPermission("system:oss:edit")
+    @Log(title = "瀵硅薄瀛樺偍閰嶇疆", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
+        return toAjax(iSysOssConfigService.updateByBo(bo));
+    }
+
+    /**
+     * 鍒犻櫎瀵硅薄瀛樺偍閰嶇疆
+     *
+     * @param ossConfigIds OSS閰嶇疆ID涓�
+     */
+    @SaCheckPermission("system:oss:remove")
+    @Log(title = "瀵硅薄瀛樺偍閰嶇疆", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ossConfigIds}")
+    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                          @PathVariable Long[] ossConfigIds) {
+        return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true));
+    }
+
+    /**
+     * 鐘舵�佷慨鏀�
+     */
+    @SaCheckPermission("system:oss:edit")
+    @Log(title = "瀵硅薄瀛樺偍鐘舵�佷慨鏀�", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus")
+    public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) {
+        return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java
new file mode 100644
index 0000000..f93d597
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java
@@ -0,0 +1,114 @@
+package com.ruoyi.system.controller.system;
+
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpException;
+import cn.hutool.http.HttpUtil;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.validate.QueryGroup;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.core.utils.file.FileUtils;
+import com.ruoyi.system.domain.bo.SysOssBo;
+import com.ruoyi.system.domain.vo.SysOssVo;
+import com.ruoyi.system.service.ISysOssService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotEmpty;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鏂囦欢涓婁紶 鎺у埗灞�
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/oss")
+public class SysOssController extends BaseController {
+
+    private final ISysOssService iSysOssService;
+
+    /**
+     * 鏌ヨOSS瀵硅薄瀛樺偍鍒楄〃
+     */
+    @SaCheckPermission("system:oss:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) {
+        return iSysOssService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 鏌ヨOSS瀵硅薄鍩轰簬id涓�
+     *
+     * @param ossIds OSS瀵硅薄ID涓�
+     */
+    @SaCheckPermission("system:oss:list")
+    @GetMapping("/listByIds/{ossIds}")
+    public R<List<SysOssVo>> listByIds(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                                       @PathVariable Long[] ossIds) {
+        List<SysOssVo> list = iSysOssService.listByIds(Arrays.asList(ossIds));
+        return R.ok(list);
+    }
+
+    /**
+     * 涓婁紶OSS瀵硅薄瀛樺偍
+     *
+     * @param file 鏂囦欢
+     */
+    @SaCheckPermission("system:oss:upload")
+    @Log(title = "OSS瀵硅薄瀛樺偍", businessType = BusinessType.INSERT)
+    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
+        if (ObjectUtil.isNull(file)) {
+            throw new ServiceException("涓婁紶鏂囦欢涓嶈兘涓虹┖");
+        }
+        SysOssVo oss = iSysOssService.upload(file);
+        Map<String, String> map = new HashMap<>(2);
+        map.put("url", oss.getUrl());
+        map.put("fileName", oss.getOriginalName());
+        map.put("ossId", oss.getOssId().toString());
+        return R.ok(map);
+    }
+
+    /**
+     * 涓嬭浇OSS瀵硅薄
+     *
+     * @param ossId OSS瀵硅薄ID
+     */
+    @SaCheckPermission("system:oss:download")
+    @GetMapping("/download/{ossId}")
+    public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
+        iSysOssService.download(ossId,response);
+    }
+
+    /**
+     * 鍒犻櫎OSS瀵硅薄瀛樺偍
+     *
+     * @param ossIds OSS瀵硅薄ID涓�
+     */
+    @SaCheckPermission("system:oss:remove")
+    @Log(title = "OSS瀵硅薄瀛樺偍", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ossIds}")
+    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+                          @PathVariable Long[] ossIds) {
+        return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true));
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java
new file mode 100644
index 0000000..4dbc18c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java
@@ -0,0 +1,115 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.service.ISysPostService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 宀椾綅淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/post")
+public class SysPostController extends BaseController {
+
+    private final ISysPostService postService;
+
+    /**
+     * 鑾峰彇宀椾綅鍒楄〃
+     */
+    @SaCheckPermission("system:post:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysPost> list(SysPost post, PageQuery pageQuery) {
+        return postService.selectPagePostList(post, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭宀椾綅鍒楄〃
+     */
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("system:post:export")
+    @PostMapping("/export")
+    public void export(SysPost post, HttpServletResponse response) {
+        List<SysPost> list = postService.selectPostList(post);
+        ExcelUtil.exportExcel(list, "宀椾綅鏁版嵁", SysPost.class, response);
+    }
+
+    /**
+     * 鏍规嵁宀椾綅缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param postId 宀椾綅ID
+     */
+    @SaCheckPermission("system:post:query")
+    @GetMapping(value = "/{postId}")
+    public R<SysPost> getInfo(@PathVariable Long postId) {
+        return R.ok(postService.selectPostById(postId));
+    }
+
+    /**
+     * 鏂板宀椾綅
+     */
+    @SaCheckPermission("system:post:add")
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysPost post) {
+        if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) {
+            return R.fail("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+        } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) {
+            return R.fail("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+        }
+        return toAjax(postService.insertPost(post));
+    }
+
+    /**
+     * 淇敼宀椾綅
+     */
+    @SaCheckPermission("system:post:edit")
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysPost post) {
+        if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) {
+            return R.fail("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+        } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) {
+            return R.fail("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+        }
+        return toAjax(postService.updatePost(post));
+    }
+
+    /**
+     * 鍒犻櫎宀椾綅
+     *
+     * @param postIds 宀椾綅ID涓�
+     */
+    @SaCheckPermission("system:post:remove")
+    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{postIds}")
+    public R<Void> remove(@PathVariable Long[] postIds) {
+        return toAjax(postService.deletePostByIds(postIds));
+    }
+
+    /**
+     * 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     */
+    @GetMapping("/optionselect")
+    public R<List<SysPost>> optionselect() {
+        List<SysPost> posts = postService.selectPostAll();
+        return R.ok(posts);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java
new file mode 100644
index 0000000..2bc05a6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java
@@ -0,0 +1,127 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.secure.BCrypt;
+import cn.hutool.core.io.FileUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.file.MimeTypeUtils;
+import com.ruoyi.system.domain.vo.SysOssVo;
+import com.ruoyi.system.service.ISysOssService;
+import com.ruoyi.system.service.ISysUserService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 涓汉淇℃伅 涓氬姟澶勭悊
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/user/profile")
+public class SysProfileController extends BaseController {
+
+    private final ISysUserService userService;
+    private final ISysOssService iSysOssService;
+
+    /**
+     * 涓汉淇℃伅
+     */
+    @GetMapping
+    public R<Map<String, Object>> profile() {
+        SysUser user = userService.selectUserById(LoginHelper.getUserId());
+        Map<String, Object> ajax = new HashMap<>();
+        ajax.put("user", user);
+        ajax.put("roleGroup", userService.selectUserRoleGroup(user.getUserName()));
+        ajax.put("postGroup", userService.selectUserPostGroup(user.getUserName()));
+        return R.ok(ajax);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛
+     */
+    @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> updateProfile(@RequestBody SysUser user) {
+        if (StringUtils.isNotEmpty(user.getPhonenumber())
+            && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
+            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+        }
+        if (StringUtils.isNotEmpty(user.getEmail())
+            && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
+            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+        }
+        user.setUserId(LoginHelper.getUserId());
+        user.setUserName(null);
+        user.setPassword(null);
+        user.setAvatar(null);
+        user.setDeptId(null);
+        if (userService.updateUserProfile(user) > 0) {
+            return R.ok();
+        }
+        return R.fail("淇敼涓汉淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
+    }
+
+    /**
+     * 閲嶇疆瀵嗙爜
+     *
+     * @param newPassword 鏃у瘑鐮�
+     * @param oldPassword 鏂板瘑鐮�
+     */
+    @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+    @PutMapping("/updatePwd")
+    public R<Void> updatePwd(String oldPassword, String newPassword) {
+        SysUser user = userService.selectUserById(LoginHelper.getUserId());
+        String userName = user.getUserName();
+        String password = user.getPassword();
+        if (!BCrypt.checkpw(oldPassword, password)) {
+            return R.fail("淇敼瀵嗙爜澶辫触锛屾棫瀵嗙爜閿欒");
+        }
+        if (BCrypt.checkpw(newPassword, password)) {
+            return R.fail("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�");
+        }
+
+        if (userService.resetUserPwd(userName, BCrypt.hashpw(newPassword)) > 0) {
+            return R.ok();
+        }
+        return R.fail("淇敼瀵嗙爜寮傚父锛岃鑱旂郴绠$悊鍛�");
+    }
+
+    /**
+     * 澶村儚涓婁紶
+     *
+     * @param avatarfile 鐢ㄦ埛澶村儚
+     */
+    @Log(title = "鐢ㄦ埛澶村儚", businessType = BusinessType.UPDATE)
+    @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Map<String, Object>> avatar(@RequestPart("avatarfile") MultipartFile avatarfile) {
+        Map<String, Object> ajax = new HashMap<>();
+        if (!avatarfile.isEmpty()) {
+            String extension = FileUtil.extName(avatarfile.getOriginalFilename());
+            if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
+                return R.fail("鏂囦欢鏍煎紡涓嶆纭紝璇蜂笂浼�" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "鏍煎紡");
+            }
+            SysOssVo oss = iSysOssService.upload(avatarfile);
+            String avatar = oss.getUrl();
+            if (userService.updateUserAvatar(LoginHelper.getUsername(), avatar)) {
+                ajax.put("imgUrl", avatar);
+                return R.ok(ajax);
+            }
+        }
+        return R.fail("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛�");
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java
new file mode 100644
index 0000000..5d749ae
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java
@@ -0,0 +1,237 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.system.domain.SysDept;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+import com.ruoyi.system.service.SysPermissionService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 瑙掕壊淇℃伅
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/role")
+public class SysRoleController extends BaseController {
+
+    private final ISysRoleService roleService;
+    private final ISysUserService userService;
+    private final ISysDeptService deptService;
+    private final SysPermissionService permissionService;
+
+    /**
+     * 鑾峰彇瑙掕壊淇℃伅鍒楄〃
+     */
+    @SaCheckPermission("system:role:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysRole> list(SysRole role, PageQuery pageQuery) {
+        return roleService.selectPageRoleList(role, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭瑙掕壊淇℃伅鍒楄〃
+     */
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("system:role:export")
+    @PostMapping("/export")
+    public void export(SysRole role, HttpServletResponse response) {
+        List<SysRole> list = roleService.selectRoleList(role);
+        ExcelUtil.exportExcel(list, "瑙掕壊鏁版嵁", SysRole.class, response);
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param roleId 瑙掕壊ID
+     */
+    @SaCheckPermission("system:role:query")
+    @GetMapping(value = "/{roleId}")
+    public R<SysRole> getInfo(@PathVariable Long roleId) {
+        roleService.checkRoleDataScope(roleId);
+        return R.ok(roleService.selectRoleById(roleId));
+    }
+
+    /**
+     * 鏂板瑙掕壊
+     */
+    @SaCheckPermission("system:role:add")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysRole role) {
+        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
+            return R.fail("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
+            return R.fail("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+        }
+        return toAjax(roleService.insertRole(role));
+
+    }
+
+    /**
+     * 淇敼淇濆瓨瑙掕壊
+     */
+    @SaCheckPermission("system:role:edit")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysRole role) {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
+            return R.fail("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
+            return R.fail("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+        }
+
+        if (roleService.updateRole(role) > 0) {
+            // 鏇存柊缂撳瓨鐢ㄦ埛鏉冮檺
+            LoginUser loginUser = LoginHelper.getLoginUser();
+            SysUser sysUser = userService.selectUserById(loginUser.getUserId());
+            if (ObjectUtil.isNotNull(sysUser) && !sysUser.isAdmin()) {
+                loginUser.setMenuPermission(permissionService.getMenuPermission(sysUser));
+                LoginHelper.setLoginUser(loginUser);
+            }
+            return R.ok();
+        }
+        return R.fail("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑱旂郴绠$悊鍛�");
+    }
+
+    /**
+     * 淇敼淇濆瓨鏁版嵁鏉冮檺
+     */
+    @SaCheckPermission("system:role:edit")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/dataScope")
+    public R<Void> dataScope(@RequestBody SysRole role) {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        return toAjax(roleService.authDataScope(role));
+    }
+
+    /**
+     * 鐘舵�佷慨鏀�
+     */
+    @SaCheckPermission("system:role:edit")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus")
+    public R<Void> changeStatus(@RequestBody SysRole role) {
+        roleService.checkRoleAllowed(role);
+        roleService.checkRoleDataScope(role.getRoleId());
+        return toAjax(roleService.updateRoleStatus(role));
+    }
+
+    /**
+     * 鍒犻櫎瑙掕壊
+     *
+     * @param roleIds 瑙掕壊ID涓�
+     */
+    @SaCheckPermission("system:role:remove")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{roleIds}")
+    public R<Void> remove(@PathVariable Long[] roleIds) {
+        return toAjax(roleService.deleteRoleByIds(roleIds));
+    }
+
+    /**
+     * 鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     */
+    @SaCheckPermission("system:role:query")
+    @GetMapping("/optionselect")
+    public R<List<SysRole>> optionselect() {
+        return R.ok(roleService.selectRoleAll());
+    }
+
+    /**
+     * 鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+     */
+    @SaCheckPermission("system:role:list")
+    @GetMapping("/authUser/allocatedList")
+    public TableDataInfo<SysUser> allocatedList(SysUser user, PageQuery pageQuery) {
+        return userService.selectAllocatedList(user, pageQuery);
+    }
+
+    /**
+     * 鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     */
+    @SaCheckPermission("system:role:list")
+    @GetMapping("/authUser/unallocatedList")
+    public TableDataInfo<SysUser> unallocatedList(SysUser user, PageQuery pageQuery) {
+        return userService.selectUnallocatedList(user, pageQuery);
+    }
+
+    /**
+     * 鍙栨秷鎺堟潈鐢ㄦ埛
+     */
+    @SaCheckPermission("system:role:edit")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authUser/cancel")
+    public R<Void> cancelAuthUser(@RequestBody SysUserRole userRole) {
+        return toAjax(roleService.deleteAuthUser(userRole));
+    }
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛
+     *
+     * @param roleId  瑙掕壊ID
+     * @param userIds 鐢ㄦ埛ID涓�
+     */
+    @SaCheckPermission("system:role:edit")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authUser/cancelAll")
+    public R<Void> cancelAuthUserAll(Long roleId, Long[] userIds) {
+        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
+    }
+
+    /**
+     * 鎵归噺閫夋嫨鐢ㄦ埛鎺堟潈
+     *
+     * @param roleId  瑙掕壊ID
+     * @param userIds 鐢ㄦ埛ID涓�
+     */
+    @SaCheckPermission("system:role:edit")
+    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authUser/selectAll")
+    public R<Void> selectAuthUserAll(Long roleId, Long[] userIds) {
+        roleService.checkRoleDataScope(roleId);
+        return toAjax(roleService.insertAuthUsers(roleId, userIds));
+    }
+
+    /**
+     * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
+     *
+     * @param roleId 瑙掕壊ID
+     */
+    @SaCheckPermission("system:role:list")
+    @GetMapping(value = "/deptTree/{roleId}")
+    public R<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
+        Map<String, Object> ajax = new HashMap<>();
+        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
+        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
+        return R.ok(ajax);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
new file mode 100644
index 0000000..de8b384
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
@@ -0,0 +1,253 @@
+package com.ruoyi.system.controller.system;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.secure.BCrypt;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.excel.core.ExcelResult;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.system.domain.SysDept;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.excel.utils.ExcelUtil;
+import com.ruoyi.system.domain.vo.SysUserExportVo;
+import com.ruoyi.system.domain.vo.SysUserImportVo;
+import com.ruoyi.system.listener.SysUserImportListener;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysPostService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鐢ㄦ埛淇℃伅
+ *
+ * @author Lion Li
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/user")
+public class SysUserController extends BaseController {
+
+    private final ISysUserService userService;
+    private final ISysRoleService roleService;
+    private final ISysPostService postService;
+    private final ISysDeptService deptService;
+
+    /**
+     * 鑾峰彇鐢ㄦ埛鍒楄〃
+     */
+    @SaCheckPermission("system:user:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysUser> list(SysUser user, PageQuery pageQuery) {
+        return userService.selectPageUserList(user, pageQuery);
+    }
+
+    /**
+     * 瀵煎嚭鐢ㄦ埛鍒楄〃
+     */
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.EXPORT)
+    @SaCheckPermission("system:user:export")
+    @PostMapping("/export")
+    public void export(SysUser user, HttpServletResponse response) {
+        List<SysUser> list = userService.selectUserList(user);
+        List<SysUserExportVo> listVo = BeanUtil.copyToList(list, SysUserExportVo.class);
+        for (int i = 0; i < list.size(); i++) {
+            SysDept dept = list.get(i).getDept();
+            SysUserExportVo vo = listVo.get(i);
+            if (ObjectUtil.isNotEmpty(dept)) {
+                vo.setDeptName(dept.getDeptName());
+                vo.setLeader(dept.getLeader());
+            }
+        }
+        ExcelUtil.exportExcel(listVo, "鐢ㄦ埛鏁版嵁", SysUserExportVo.class, response);
+    }
+
+    /**
+     * 瀵煎叆鏁版嵁
+     *
+     * @param file          瀵煎叆鏂囦欢
+     * @param updateSupport 鏄惁鏇存柊宸插瓨鍦ㄦ暟鎹�
+     */
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.IMPORT)
+    @SaCheckPermission("system:user:import")
+    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
+        ExcelResult<SysUserImportVo> result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport));
+        return R.ok(result.getAnalysis());
+    }
+
+    /**
+     * 鑾峰彇瀵煎叆妯℃澘
+     */
+    @PostMapping("/importTemplate")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil.exportExcel(new ArrayList<>(), "鐢ㄦ埛鏁版嵁", SysUserImportVo.class, response);
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇璇︾粏淇℃伅
+     *
+     * @param userId 鐢ㄦ埛ID
+     */
+    @SaCheckPermission("system:user:query")
+    @GetMapping(value = {"/", "/{userId}"})
+    public R<Map<String, Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId) {
+        userService.checkUserDataScope(userId);
+        Map<String, Object> ajax = new HashMap<>();
+        List<SysRole> roles = roleService.selectRoleAll();
+        ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
+        ajax.put("posts", postService.selectPostAll());
+        if (ObjectUtil.isNotNull(userId)) {
+            SysUser sysUser = userService.selectUserById(userId);
+            ajax.put("user", sysUser);
+            ajax.put("postIds", postService.selectPostListByUserId(userId));
+            ajax.put("roleIds", StreamUtils.toList(sysUser.getRoles(), SysRole::getRoleId));
+        }
+        return R.ok(ajax);
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛
+     */
+    @SaCheckPermission("system:user:add")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R<Void> add(@Validated @RequestBody SysUser user) {
+        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) {
+            return R.fail("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
+            && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
+            return R.fail("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+        } else if (StringUtils.isNotEmpty(user.getEmail())
+            && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
+            return R.fail("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+        }
+        user.setPassword(BCrypt.hashpw(user.getPassword()));
+        return toAjax(userService.insertUser(user));
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛
+     */
+    @SaCheckPermission("system:user:edit")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public R<Void> edit(@Validated @RequestBody SysUser user) {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) {
+            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
+            && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
+            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+        } else if (StringUtils.isNotEmpty(user.getEmail())
+            && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
+            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+        }
+        return toAjax(userService.updateUser(user));
+    }
+
+    /**
+     * 鍒犻櫎鐢ㄦ埛
+     *
+     * @param userIds 瑙掕壊ID涓�
+     */
+    @SaCheckPermission("system:user:remove")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{userIds}")
+    public R<Void> remove(@PathVariable Long[] userIds) {
+        if (ArrayUtil.contains(userIds, LoginHelper.getUserId())) {
+            return R.fail("褰撳墠鐢ㄦ埛涓嶈兘鍒犻櫎");
+        }
+        return toAjax(userService.deleteUserByIds(userIds));
+    }
+
+    /**
+     * 閲嶇疆瀵嗙爜
+     */
+    @SaCheckPermission("system:user:resetPwd")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/resetPwd")
+    public R<Void> resetPwd(@RequestBody SysUser user) {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        user.setPassword(BCrypt.hashpw(user.getPassword()));
+        return toAjax(userService.resetPwd(user));
+    }
+
+    /**
+     * 鐘舵�佷慨鏀�
+     */
+    @SaCheckPermission("system:user:edit")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus")
+    public R<Void> changeStatus(@RequestBody SysUser user) {
+        userService.checkUserAllowed(user);
+        userService.checkUserDataScope(user.getUserId());
+        return toAjax(userService.updateUserStatus(user));
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇鎺堟潈瑙掕壊
+     *
+     * @param userId 鐢ㄦ埛ID
+     */
+    @SaCheckPermission("system:user:query")
+    @GetMapping("/authRole/{userId}")
+    public R<Map<String, Object>> authRole(@PathVariable Long userId) {
+        SysUser user = userService.selectUserById(userId);
+        List<SysRole> roles = roleService.selectRolesByUserId(userId);
+        Map<String, Object> ajax = new HashMap<>();
+        ajax.put("user", user);
+        ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
+        return R.ok(ajax);
+    }
+
+    /**
+     * 鐢ㄦ埛鎺堟潈瑙掕壊
+     *
+     * @param userId  鐢ㄦ埛Id
+     * @param roleIds 瑙掕壊ID涓�
+     */
+    @SaCheckPermission("system:user:edit")
+    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.GRANT)
+    @PutMapping("/authRole")
+    public R<Void> insertAuthRole(Long userId, Long[] roleIds) {
+        userService.checkUserDataScope(userId);
+        userService.insertUserAuth(userId, roleIds);
+        return R.ok();
+    }
+
+    /**
+     * 鑾峰彇閮ㄩ棬鏍戝垪琛�
+     */
+    @SaCheckPermission("system:user:list")
+    @GetMapping("/deptTree")
+    public R<List<Tree<Long>>> deptTree(SysDept dept) {
+        return R.ok(deptService.selectDeptTreeList(dept));
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java
new file mode 100644
index 0000000..ac4e0af
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java
@@ -0,0 +1,47 @@
+package com.ruoyi.system.domain;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 缂撳瓨淇℃伅
+ *
+ * @author Lion Li
+ */
+@Data
+@NoArgsConstructor
+public class SysCache {
+
+    /**
+     * 缂撳瓨鍚嶇О
+     */
+    private String cacheName = "";
+
+    /**
+     * 缂撳瓨閿悕
+     */
+    private String cacheKey = "";
+
+    /**
+     * 缂撳瓨鍐呭
+     */
+    private String cacheValue = "";
+
+    /**
+     * 澶囨敞
+     */
+    private String remark = "";
+
+    public SysCache(String cacheName, String remark) {
+        this.cacheName = cacheName;
+        this.remark = remark;
+    }
+
+    public SysCache(String cacheName, String cacheKey, String cacheValue) {
+        this.cacheName = StringUtils.replace(cacheName, ":", "");
+        this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
+        this.cacheValue = cacheValue;
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
new file mode 100644
index 0000000..831eca5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
@@ -0,0 +1,71 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
+/**
+ * 鍙傛暟閰嶇疆琛� sys_config
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_config")
+@ExcelIgnoreUnannotated
+public class SysConfig extends BaseEntity {
+
+    /**
+     * 鍙傛暟涓婚敭
+     */
+    @ExcelProperty(value = "鍙傛暟涓婚敭")
+    @TableId(value = "config_id")
+    private Long configId;
+
+    /**
+     * 鍙傛暟鍚嶇О
+     */
+    @ExcelProperty(value = "鍙傛暟鍚嶇О")
+    @NotBlank(message = "鍙傛暟鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "鍙傛暟鍚嶇О涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String configName;
+
+    /**
+     * 鍙傛暟閿悕
+     */
+    @ExcelProperty(value = "鍙傛暟閿悕")
+    @NotBlank(message = "鍙傛暟閿悕闀垮害涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "鍙傛暟閿悕闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String configKey;
+
+    /**
+     * 鍙傛暟閿��
+     */
+    @ExcelProperty(value = "鍙傛暟閿��")
+    @NotBlank(message = "鍙傛暟閿�间笉鑳戒负绌�")
+    @Size(min = 0, max = 500, message = "鍙傛暟閿�奸暱搴︿笉鑳借秴杩噞max}涓瓧绗�")
+    private String configValue;
+
+    /**
+     * 绯荤粺鍐呯疆锛圷鏄� N鍚︼級
+     */
+    @ExcelProperty(value = "绯荤粺鍐呯疆", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_yes_no")
+    private String configType;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
new file mode 100644
index 0000000..0ade3b3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
@@ -0,0 +1,83 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.web.domain.TreeEntity;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 閮ㄩ棬琛� sys_dept
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_dept")
+public class SysDept extends TreeEntity<SysDept> {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    @TableId(value = "dept_id")
+    private Long deptId;
+
+    /**
+     * 閮ㄩ棬鍚嶇О
+     */
+    @NotBlank(message = "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 30, message = "閮ㄩ棬鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String deptName;
+
+    /**
+     * 鏄剧ず椤哄簭
+     */
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    private Integer orderNum;
+
+    /**
+     * 璐熻矗浜�
+     */
+    private String leader;
+
+    /**
+     * 鑱旂郴鐢佃瘽
+     */
+    @Size(min = 0, max = 11, message = "鑱旂郴鐢佃瘽闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String phone;
+
+    /**
+     * 閭
+     */
+    @Email(message = "閭鏍煎紡涓嶆纭�")
+    @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String email;
+
+    /**
+     * 閮ㄩ棬鐘舵��:0姝e父,1鍋滅敤
+     */
+    private String status;
+
+    /**
+     * 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 绁栫骇鍒楄〃
+     */
+    private String ancestors;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java
new file mode 100644
index 0000000..82e1258
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java
@@ -0,0 +1,100 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
+/**
+ * 瀛楀吀鏁版嵁琛� sys_dict_data
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_dict_data")
+@ExcelIgnoreUnannotated
+public class SysDictData extends BaseEntity {
+
+    /**
+     * 瀛楀吀缂栫爜
+     */
+    @ExcelProperty(value = "瀛楀吀缂栫爜")
+    @TableId(value = "dict_code")
+    private Long dictCode;
+
+    /**
+     * 瀛楀吀鎺掑簭
+     */
+    @ExcelProperty(value = "瀛楀吀鎺掑簭")
+    private Integer dictSort;
+
+    /**
+     * 瀛楀吀鏍囩
+     */
+    @ExcelProperty(value = "瀛楀吀鏍囩")
+    @NotBlank(message = "瀛楀吀鏍囩涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀鏍囩闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String dictLabel;
+
+    /**
+     * 瀛楀吀閿��
+     */
+    @ExcelProperty(value = "瀛楀吀閿��")
+    @NotBlank(message = "瀛楀吀閿�间笉鑳戒负绌�")
+    @Size(min = 0, max = 100, message = "瀛楀吀閿�奸暱搴︿笉鑳借秴杩噞max}涓瓧绗�")
+    private String dictValue;
+
+    /**
+     * 瀛楀吀绫诲瀷
+     */
+    @ExcelProperty(value = "瀛楀吀绫诲瀷")
+    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String dictType;
+
+    /**
+     * 鏍峰紡灞炴�э紙鍏朵粬鏍峰紡鎵╁睍锛�
+     */
+    @Size(min = 0, max = 100, message = "鏍峰紡灞炴�ч暱搴︿笉鑳借秴杩噞max}涓瓧绗�")
+    private String cssClass;
+
+    /**
+     * 琛ㄦ牸瀛楀吀鏍峰紡
+     */
+    private String listClass;
+
+    /**
+     * 鏄惁榛樿锛圷鏄� N鍚︼級
+     */
+    @ExcelProperty(value = "鏄惁榛樿", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_yes_no")
+    private String isDefault;
+
+    /**
+     * 鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_normal_disable")
+    private String status;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    public boolean getDefault() {
+        return UserConstants.YES.equals(this.isDefault);
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java
new file mode 100644
index 0000000..514200b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java
@@ -0,0 +1,65 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+
+/**
+ * 瀛楀吀绫诲瀷琛� sys_dict_type
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_dict_type")
+@ExcelIgnoreUnannotated
+public class SysDictType extends BaseEntity {
+
+    /**
+     * 瀛楀吀涓婚敭
+     */
+    @ExcelProperty(value = "瀛楀吀涓婚敭")
+    @TableId(value = "dict_id")
+    private Long dictId;
+
+    /**
+     * 瀛楀吀鍚嶇О
+     */
+    @ExcelProperty(value = "瀛楀吀鍚嶇О")
+    @NotBlank(message = "瀛楀吀鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String dictName;
+
+    /**
+     * 瀛楀吀绫诲瀷
+     */
+    @ExcelProperty(value = "瀛楀吀绫诲瀷")
+    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷绫诲瀷闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "瀛楀吀绫诲瀷蹇呴』浠ュ瓧姣嶅紑澶达紝涓斿彧鑳戒负锛堝皬鍐欏瓧姣嶏紝鏁板瓧锛屼笅婊戠嚎锛�")
+    private String dictType;
+
+    /**
+     * 鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_normal_disable")
+    private String status;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
new file mode 100644
index 0000000..047936f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
@@ -0,0 +1,94 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 绯荤粺璁块棶璁板綍琛� sys_logininfor
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys_logininfor")
+@ExcelIgnoreUnannotated
+public class SysLogininfor implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ExcelProperty(value = "搴忓彿")
+    @TableId(value = "info_id")
+    private Long infoId;
+
+    /**
+     * 鐢ㄦ埛璐﹀彿
+     */
+    @ExcelProperty(value = "鐢ㄦ埛璐﹀彿")
+    private String userName;
+
+    /**
+     * 鐧诲綍鐘舵�� 0鎴愬姛 1澶辫触
+     */
+    @ExcelProperty(value = "鐧诲綍鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_common_status")
+    private String status;
+
+    /**
+     * 鐧诲綍IP鍦板潃
+     */
+    @ExcelProperty(value = "鐧诲綍鍦板潃")
+    private String ipaddr;
+
+    /**
+     * 鐧诲綍鍦扮偣
+     */
+    @ExcelProperty(value = "鐧诲綍鍦扮偣")
+    private String loginLocation;
+
+    /**
+     * 娴忚鍣ㄧ被鍨�
+     */
+    @ExcelProperty(value = "娴忚鍣�")
+    private String browser;
+
+    /**
+     * 鎿嶄綔绯荤粺
+     */
+    @ExcelProperty(value = "鎿嶄綔绯荤粺")
+    private String os;
+
+    /**
+     * 鎻愮ず娑堟伅
+     */
+    @ExcelProperty(value = "鎻愮ず娑堟伅")
+    private String msg;
+
+    /**
+     * 璁块棶鏃堕棿
+     */
+    @ExcelProperty(value = "璁块棶鏃堕棿")
+    private Date loginTime;
+
+    /**
+     * 璇锋眰鍙傛暟
+     */
+    @TableField(exist = false)
+    private Map<String, Object> params = new HashMap<>();
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
new file mode 100644
index 0000000..c6a4a4f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
@@ -0,0 +1,104 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.core.web.domain.TreeEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+
+/**
+ * 鑿滃崟鏉冮檺琛� sys_menu
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_menu")
+public class SysMenu extends TreeEntity<SysMenu> {
+
+    /**
+     * 鑿滃崟ID
+     */
+    @TableId(value = "menu_id")
+    private Long menuId;
+
+    /**
+     * 鑿滃崟鍚嶇О
+     */
+    @NotBlank(message = "鑿滃崟鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 50, message = "鑿滃崟鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String menuName;
+
+    /**
+     * 鏄剧ず椤哄簭
+     */
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    private Integer orderNum;
+
+    /**
+     * 璺敱鍦板潃
+     */
+    @Size(min = 0, max = 200, message = "璺敱鍦板潃涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String path;
+
+    /**
+     * 缁勪欢璺緞
+     */
+    @Size(min = 0, max = 200, message = "缁勪欢璺緞涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String component;
+
+    /**
+     * 璺敱鍙傛暟
+     */
+    private String queryParam;
+
+    /**
+     * 鏄惁涓哄閾撅紙0鏄� 1鍚︼級
+     */
+    private String isFrame;
+
+    /**
+     * 鏄惁缂撳瓨锛�0缂撳瓨 1涓嶇紦瀛橈級
+     */
+    private String isCache;
+
+    /**
+     * 绫诲瀷锛圡鐩綍 C鑿滃崟 F鎸夐挳锛�
+     */
+    @NotBlank(message = "鑿滃崟绫诲瀷涓嶈兘涓虹┖")
+    private String menuType;
+
+    /**
+     * 鏄剧ず鐘舵�侊紙0鏄剧ず 1闅愯棌锛�
+     */
+    private String visible;
+
+    /**
+     * 鑿滃崟鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    private String status;
+
+    /**
+     * 鏉冮檺瀛楃涓�
+     */
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    @Size(min = 0, max = 100, message = "鏉冮檺鏍囪瘑闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String perms;
+
+    /**
+     * 鑿滃崟鍥炬爣
+     */
+    private String icon;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
new file mode 100644
index 0000000..c4c1b1d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
@@ -0,0 +1,58 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.core.xss.Xss;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
+
+/**
+ * 閫氱煡鍏憡琛� sys_notice
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_notice")
+public class SysNotice extends BaseEntity {
+
+    /**
+     * 鍏憡ID
+     */
+    @TableId(value = "notice_id")
+    private Long noticeId;
+
+    /**
+     * 鍏憡鏍囬
+     */
+    @Xss(message = "鍏憡鏍囬涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @NotBlank(message = "鍏憡鏍囬涓嶈兘涓虹┖")
+    @Size(min = 0, max = 50, message = "鍏憡鏍囬涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String noticeTitle;
+
+    /**
+     * 鍏憡绫诲瀷锛�1閫氱煡 2鍏憡锛�
+     */
+    private String noticeType;
+
+    /**
+     * 鍏憡鍐呭
+     */
+    private String noticeContent;
+
+    /**
+     * 鍏憡鐘舵�侊紙0姝e父 1鍏抽棴锛�
+     */
+    private String status;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
new file mode 100644
index 0000000..0486569
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
@@ -0,0 +1,144 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍琛� oper_log
+ *
+ * @author Lion Li
+ */
+
+@Data
+@TableName("sys_oper_log")
+@ExcelIgnoreUnannotated
+public class SysOperLog implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鏃ュ織涓婚敭
+     */
+    @ExcelProperty(value = "鏃ュ織涓婚敭")
+    @TableId(value = "oper_id")
+    private Long operId;
+
+    /**
+     * 鎿嶄綔妯″潡
+     */
+    @ExcelProperty(value = "鎿嶄綔妯″潡")
+    private String title;
+
+    /**
+     * 涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛�
+     */
+    @ExcelProperty(value = "涓氬姟绫诲瀷", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_oper_type")
+    private Integer businessType;
+
+    /**
+     * 涓氬姟绫诲瀷鏁扮粍
+     */
+    @TableField(exist = false)
+    private Integer[] businessTypes;
+
+    /**
+     * 璇锋眰鏂规硶
+     */
+    @ExcelProperty(value = "璇锋眰鏂规硶")
+    private String method;
+
+    /**
+     * 璇锋眰鏂瑰紡
+     */
+    @ExcelProperty(value = "璇锋眰鏂瑰紡")
+    private String requestMethod;
+
+    /**
+     * 鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級
+     */
+    @ExcelProperty(value = "鎿嶄綔绫诲埆", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=鍏跺畠,1=鍚庡彴鐢ㄦ埛,2=鎵嬫満绔敤鎴�")
+    private Integer operatorType;
+
+    /**
+     * 鎿嶄綔浜哄憳
+     */
+    @ExcelProperty(value = "鎿嶄綔浜哄憳")
+    private String operName;
+
+    /**
+     * 閮ㄩ棬鍚嶇О
+     */
+    @ExcelProperty(value = "閮ㄩ棬鍚嶇О")
+    private String deptName;
+
+    /**
+     * 璇锋眰url
+     */
+    @ExcelProperty(value = "璇锋眰鍦板潃")
+    private String operUrl;
+
+    /**
+     * 鎿嶄綔鍦板潃
+     */
+    @ExcelProperty(value = "鎿嶄綔鍦板潃")
+    private String operIp;
+
+    /**
+     * 鎿嶄綔鍦扮偣
+     */
+    @ExcelProperty(value = "鎿嶄綔鍦扮偣")
+    private String operLocation;
+
+    /**
+     * 璇锋眰鍙傛暟
+     */
+    @ExcelProperty(value = "璇锋眰鍙傛暟")
+    private String operParam;
+
+    /**
+     * 杩斿洖鍙傛暟
+     */
+    @ExcelProperty(value = "杩斿洖鍙傛暟")
+    private String jsonResult;
+
+    /**
+     * 鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛�
+     */
+    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_common_status")
+    private Integer status;
+
+    /**
+     * 閿欒娑堟伅
+     */
+    @ExcelProperty(value = "閿欒娑堟伅")
+    private String errorMsg;
+
+    /**
+     * 鎿嶄綔鏃堕棿
+     */
+    @ExcelProperty(value = "鎿嶄綔鏃堕棿")
+    private Date operTime;
+
+    /**
+     * 璇锋眰鍙傛暟
+     */
+    @TableField(exist = false)
+    private Map<String, Object> params = new HashMap<>();
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java
new file mode 100644
index 0000000..666f6d0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java
@@ -0,0 +1,50 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * OSS瀵硅薄瀛樺偍瀵硅薄
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_oss")
+public class SysOss extends BaseEntity {
+
+    /**
+     * 瀵硅薄瀛樺偍涓婚敭
+     */
+    @TableId(value = "oss_id")
+    private Long ossId;
+
+    /**
+     * 鏂囦欢鍚�
+     */
+    private String fileName;
+
+    /**
+     * 鍘熷悕
+     */
+    private String originalName;
+
+    /**
+     * 鏂囦欢鍚庣紑鍚�
+     */
+    private String fileSuffix;
+
+    /**
+     * URL鍦板潃
+     */
+    private String url;
+
+    /**
+     * 鏈嶅姟鍟�
+     */
+    private String service;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
new file mode 100644
index 0000000..fcba9d0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
@@ -0,0 +1,89 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 瀵硅薄瀛樺偍閰嶇疆瀵硅薄 sys_oss_config
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_oss_config")
+public class SysOssConfig extends BaseEntity {
+
+    /**
+     * 涓诲缓
+     */
+    @TableId(value = "oss_config_id")
+    private Long ossConfigId;
+
+    /**
+     * 閰嶇疆key
+     */
+    private String configKey;
+
+    /**
+     * accessKey
+     */
+    private String accessKey;
+
+    /**
+     * 绉橀挜
+     */
+    private String secretKey;
+
+    /**
+     * 妗跺悕绉�
+     */
+    private String bucketName;
+
+    /**
+     * 鍓嶇紑
+     */
+    private String prefix;
+
+    /**
+     * 璁块棶绔欑偣
+     */
+    private String endpoint;
+
+    /**
+     * 鑷畾涔夊煙鍚�
+     */
+    private String domain;
+
+    /**
+     * 鏄惁https锛�0鍚� 1鏄級
+     */
+    private String isHttps;
+
+    /**
+     * 鍩�
+     */
+    private String region;
+
+    /**
+     * 鏄惁榛樿锛�0=鏄�,1=鍚︼級
+     */
+    private String status;
+
+    /**
+     * 鎵╁睍瀛楁
+     */
+    private String ext1;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    /**
+     * 妗舵潈闄愮被鍨�(0private 1public 2custom)
+     */
+    private String accessPolicy;
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
new file mode 100644
index 0000000..e902402
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
@@ -0,0 +1,78 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+
+/**
+ * 宀椾綅琛� sys_post
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_post")
+@ExcelIgnoreUnannotated
+public class SysPost extends BaseEntity {
+
+    /**
+     * 宀椾綅搴忓彿
+     */
+    @ExcelProperty(value = "宀椾綅搴忓彿")
+    @TableId(value = "post_id")
+    private Long postId;
+
+    /**
+     * 宀椾綅缂栫爜
+     */
+    @ExcelProperty(value = "宀椾綅缂栫爜")
+    @NotBlank(message = "宀椾綅缂栫爜涓嶈兘涓虹┖")
+    @Size(min = 0, max = 64, message = "宀椾綅缂栫爜闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String postCode;
+
+    /**
+     * 宀椾綅鍚嶇О
+     */
+    @ExcelProperty(value = "宀椾綅鍚嶇О")
+    @NotBlank(message = "宀椾綅鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 50, message = "宀椾綅鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String postName;
+
+    /**
+     * 宀椾綅鎺掑簭
+     */
+    @ExcelProperty(value = "宀椾綅鎺掑簭")
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    private Integer postSort;
+
+    /**
+     * 鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_normal_disable")
+    private String status;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    /**
+     * 鐢ㄦ埛鏄惁瀛樺湪姝ゅ矖浣嶆爣璇� 榛樿涓嶅瓨鍦�
+     */
+    @TableField(exist = false)
+    private boolean flag = false;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
new file mode 100644
index 0000000..a897208
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
@@ -0,0 +1,131 @@
+package com.ruoyi.system.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.util.Set;
+
+/**
+ * 瑙掕壊琛� sys_role
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_role")
+@ExcelIgnoreUnannotated
+public class SysRole extends BaseEntity {
+
+    /**
+     * 瑙掕壊ID
+     */
+    @ExcelProperty(value = "瑙掕壊搴忓彿")
+    @TableId(value = "role_id")
+    private Long roleId;
+
+    /**
+     * 瑙掕壊鍚嶇О
+     */
+    @ExcelProperty(value = "瑙掕壊鍚嶇О")
+    @NotBlank(message = "瑙掕壊鍚嶇О涓嶈兘涓虹┖")
+    @Size(min = 0, max = 30, message = "瑙掕壊鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String roleName;
+
+    /**
+     * 瑙掕壊鏉冮檺
+     */
+    @ExcelProperty(value = "瑙掕壊鏉冮檺")
+    @NotBlank(message = "鏉冮檺瀛楃涓嶈兘涓虹┖")
+    @Size(min = 0, max = 100, message = "鏉冮檺瀛楃闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String roleKey;
+
+    /**
+     * 瑙掕壊鎺掑簭
+     */
+    @ExcelProperty(value = "瑙掕壊鎺掑簭")
+    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+    private Integer roleSort;
+
+    /**
+     * 鏁版嵁鑼冨洿锛�1锛氭墍鏈夋暟鎹潈闄愶紱2锛氳嚜瀹氫箟鏁版嵁鏉冮檺锛�3锛氭湰閮ㄩ棬鏁版嵁鏉冮檺锛�4锛氭湰閮ㄩ棬鍙婁互涓嬫暟鎹潈闄愶紱5锛氫粎鏈汉鏁版嵁鏉冮檺锛�
+     */
+    @ExcelProperty(value = "鏁版嵁鑼冨洿", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "1=鎵�鏈夋暟鎹潈闄�,2=鑷畾涔夋暟鎹潈闄�,3=鏈儴闂ㄦ暟鎹潈闄�,4=鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺,5=浠呮湰浜烘暟鎹潈闄�")
+    private String dataScope;
+
+    /**
+     * 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙 0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀猴級
+     */
+    private Boolean menuCheckStrictly;
+
+    /**
+     * 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀� 锛�
+     */
+    private Boolean deptCheckStrictly;
+
+    /**
+     * 瑙掕壊鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    @ExcelProperty(value = "瑙掕壊鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_normal_disable")
+    private String status;
+
+    /**
+     * 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    /**
+     * 鐢ㄦ埛鏄惁瀛樺湪姝よ鑹叉爣璇� 榛樿涓嶅瓨鍦�
+     */
+    @TableField(exist = false)
+    private boolean flag = false;
+
+    /**
+     * 鑿滃崟缁�
+     */
+    @TableField(exist = false)
+    private Long[] menuIds;
+
+    /**
+     * 閮ㄩ棬缁勶紙鏁版嵁鏉冮檺锛�
+     */
+    @TableField(exist = false)
+    private Long[] deptIds;
+
+    /**
+     * 瑙掕壊鑿滃崟鏉冮檺
+     */
+    @TableField(exist = false)
+    private Set<String> permissions;
+
+    public SysRole(Long roleId) {
+        this.roleId = roleId;
+    }
+
+    public boolean isAdmin() {
+        return UserConstants.ADMIN_ID.equals(this.roleId);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
new file mode 100644
index 0000000..d604a94
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
@@ -0,0 +1,160 @@
+package com.ruoyi.system.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.ruoyi.common.core.annotation.Sensitive;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.core.enums.SensitiveStrategy;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.core.xss.Xss;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 鐢ㄦ埛瀵硅薄 sys_user
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_user")
+public class SysUser extends BaseEntity {
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    @TableId(value = "user_id")
+    private Long userId;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛璐﹀彿
+     */
+    @Xss(message = "鐢ㄦ埛璐﹀彿涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @NotBlank(message = "鐢ㄦ埛璐﹀彿涓嶈兘涓虹┖")
+    @Size(min = 0, max = 30, message = "鐢ㄦ埛璐﹀彿闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String userName;
+
+    /**
+     * 鐢ㄦ埛鏄电О
+     */
+    @Xss(message = "鐢ㄦ埛鏄电О涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @Size(min = 0, max = 30, message = "鐢ㄦ埛鏄电О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String nickName;
+
+    /**
+     * 鐢ㄦ埛绫诲瀷锛坰ys_user绯荤粺鐢ㄦ埛锛�
+     */
+    private String userType;
+
+    /**
+     * 鐢ㄦ埛閭
+     */
+    @Sensitive(strategy = SensitiveStrategy.EMAIL)
+    @Email(message = "閭鏍煎紡涓嶆纭�")
+    @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
+    private String email;
+
+    /**
+     * 鎵嬫満鍙风爜
+     */
+    @Sensitive(strategy = SensitiveStrategy.PHONE)
+    private String phonenumber;
+
+    /**
+     * 鐢ㄦ埛鎬у埆
+     */
+    private String sex;
+
+    /**
+     * 鐢ㄦ埛澶村儚
+     */
+    private String avatar;
+
+    /**
+     * 瀵嗙爜
+     */
+    @TableField(
+        insertStrategy = FieldStrategy.NOT_EMPTY,
+        updateStrategy = FieldStrategy.NOT_EMPTY,
+        whereStrategy = FieldStrategy.NOT_EMPTY
+    )
+    private String password;
+
+    /**
+     * 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    private String status;
+
+    /**
+     * 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 鏈�鍚庣櫥褰旾P
+     */
+    private String loginIp;
+
+    /**
+     * 鏈�鍚庣櫥褰曟椂闂�
+     */
+    private Date loginDate;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    /**
+     * 閮ㄩ棬瀵硅薄
+     */
+    @TableField(exist = false)
+    private SysDept dept;
+
+    /**
+     * 瑙掕壊瀵硅薄
+     */
+    @TableField(exist = false)
+    private List<SysRole> roles;
+
+    /**
+     * 瑙掕壊缁�
+     */
+    @TableField(exist = false)
+    private Long[] roleIds;
+
+    /**
+     * 宀椾綅缁�
+     */
+    @TableField(exist = false)
+    private Long[] postIds;
+
+    /**
+     * 鏁版嵁鏉冮檺 褰撳墠瑙掕壊ID
+     */
+    @TableField(exist = false)
+    private Long roleId;
+
+    public SysUser(Long userId) {
+        this.userId = userId;
+    }
+
+    public boolean isAdmin() {
+        return UserConstants.ADMIN_ID.equals(this.userId);
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java
new file mode 100644
index 0000000..d974df8
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java
@@ -0,0 +1,37 @@
+package com.ruoyi.system.domain.bo;
+
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * OSS瀵硅薄瀛樺偍鍒嗛〉鏌ヨ瀵硅薄 sys_oss
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SysOssBo extends BaseEntity {
+
+    /**
+     * 鏂囦欢鍚�
+     */
+    private String fileName;
+    /**
+     * 鍘熷悕
+     */
+    private String originalName;
+    /**
+     * 鏂囦欢鍚庣紑鍚�
+     */
+    private String fileSuffix;
+    /**
+     * URL鍦板潃
+     */
+    private String url;
+    /**
+     * 鏈嶅姟鍟�
+     */
+    private String service;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
new file mode 100644
index 0000000..2766f13
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
@@ -0,0 +1,107 @@
+package com.ruoyi.system.domain.bo;
+
+import com.ruoyi.common.core.web.domain.BaseEntity;
+import com.ruoyi.common.core.validate.AddGroup;
+import com.ruoyi.common.core.validate.EditGroup;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+
+/**
+ * 瀵硅薄瀛樺偍閰嶇疆涓氬姟瀵硅薄 sys_oss_config
+ *
+ * @author Lion Li
+ * @author 瀛よ垷鐑熼洦
+ * @date 2021-08-13
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SysOssConfigBo extends BaseEntity {
+
+    /**
+     * 涓诲缓
+     */
+    @NotNull(message = "涓诲缓涓嶈兘涓虹┖", groups = {EditGroup.class})
+    private Long ossConfigId;
+
+    /**
+     * 閰嶇疆key
+     */
+    @NotBlank(message = "閰嶇疆key涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    @Size(min = 2, max = 100, message = "configKey闀垮害蹇呴』浠嬩簬{min}鍜寋max} 涔嬮棿")
+    private String configKey;
+
+    /**
+     * accessKey
+     */
+    @NotBlank(message = "accessKey涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    @Size(min = 2, max = 100, message = "accessKey闀垮害蹇呴』浠嬩簬{min}鍜寋max} 涔嬮棿")
+    private String accessKey;
+
+    /**
+     * 绉橀挜
+     */
+    @NotBlank(message = "secretKey涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    @Size(min = 2, max = 100, message = "secretKey闀垮害蹇呴』浠嬩簬{min}鍜寋max} 涔嬮棿")
+    private String secretKey;
+
+    /**
+     * 妗跺悕绉�
+     */
+    @NotBlank(message = "妗跺悕绉颁笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
+    @Size(min = 2, max = 100, message = "bucketName闀垮害蹇呴』浠嬩簬{min}鍜寋max}涔嬮棿")
+    private String bucketName;
+
+    /**
+     * 鍓嶇紑
+     */
+    private String prefix;
+
+    /**
+     * 璁块棶绔欑偣
+     */
+    @NotBlank(message = "璁块棶绔欑偣涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
+    @Size(min = 2, max = 100, message = "endpoint闀垮害蹇呴』浠嬩簬{min}鍜寋max}涔嬮棿")
+    private String endpoint;
+
+    /**
+     * 鑷畾涔夊煙鍚�
+     */
+    private String domain;
+
+    /**
+     * 鏄惁https锛圷=鏄�,N=鍚︼級
+     */
+    private String isHttps;
+
+    /**
+     * 鏄惁榛樿锛�0=鏄�,1=鍚︼級
+     */
+    private String status;
+
+    /**
+     * 鍩�
+     */
+    private String region;
+
+    /**
+     * 鎵╁睍瀛楁
+     */
+    private String ext1;
+
+    /**
+     * 澶囨敞
+     */
+    private String remark;
+
+    /**
+     * 妗舵潈闄愮被鍨�(0private 1public 2custom)
+     */
+    @NotBlank(message = "妗舵潈闄愮被鍨嬩笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
+    private String accessPolicy;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java
new file mode 100644
index 0000000..a8606f3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.domain.vo;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import lombok.Data;
+
+/**
+ * 璺敱鏄剧ず淇℃伅
+ *
+ * @author ruoyi
+ */
+
+@Data
+public class MetaVo {
+
+    /**
+     * 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
+     */
+    private String title;
+
+    /**
+     * 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
+     */
+    private String icon;
+
+    /**
+     * 璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive>缂撳瓨
+     */
+    private boolean noCache;
+
+    /**
+     * 鍐呴摼鍦板潃锛坔ttp(s)://寮�澶达級
+     */
+    private String link;
+
+    public MetaVo(String title, String icon) {
+        this.title = title;
+        this.icon = icon;
+    }
+
+    public MetaVo(String title, String icon, boolean noCache) {
+        this.title = title;
+        this.icon = icon;
+        this.noCache = noCache;
+    }
+
+    public MetaVo(String title, String icon, String link) {
+        this.title = title;
+        this.icon = icon;
+        this.link = link;
+    }
+
+    public MetaVo(String title, String icon, boolean noCache, String link) {
+        this.title = title;
+        this.icon = icon;
+        this.noCache = noCache;
+        if (StringUtils.ishttp(link)) {
+            this.link = link;
+        }
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java
new file mode 100644
index 0000000..7758f78
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java
@@ -0,0 +1,94 @@
+package com.ruoyi.system.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 鐢ㄦ埛瀵硅薄瀵煎嚭VO
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+public class SysUserExportVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    @ExcelProperty(value = "鐢ㄦ埛搴忓彿")
+    private Long userId;
+
+    /**
+     * 鐢ㄦ埛璐﹀彿
+     */
+    @ExcelProperty(value = "鐧诲綍鍚嶇О")
+    private String userName;
+
+    /**
+     * 鐢ㄦ埛鏄电О
+     */
+    @ExcelProperty(value = "鐢ㄦ埛鍚嶇О")
+    private String nickName;
+
+    /**
+     * 鐢ㄦ埛閭
+     */
+    @ExcelProperty(value = "鐢ㄦ埛閭")
+    private String email;
+
+    /**
+     * 鎵嬫満鍙风爜
+     */
+    @ExcelProperty(value = "鎵嬫満鍙风爜")
+    private String phonenumber;
+
+    /**
+     * 鐢ㄦ埛鎬у埆
+     */
+    @ExcelProperty(value = "鐢ㄦ埛鎬у埆", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_user_sex")
+    private String sex;
+
+    /**
+     * 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    @ExcelProperty(value = "甯愬彿鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_normal_disable")
+    private String status;
+
+    /**
+     * 鏈�鍚庣櫥褰旾P
+     */
+    @ExcelProperty(value = "鏈�鍚庣櫥褰旾P")
+    private String loginIp;
+
+    /**
+     * 鏈�鍚庣櫥褰曟椂闂�
+     */
+    @ExcelProperty(value = "鏈�鍚庣櫥褰曟椂闂�")
+    private Date loginDate;
+
+    /**
+     * 閮ㄩ棬鍚嶇О
+     */
+    @ExcelProperty(value = "閮ㄩ棬鍚嶇О")
+    private String deptName;
+
+    /**
+     * 璐熻矗浜�
+     */
+    @ExcelProperty(value = "閮ㄩ棬璐熻矗浜�")
+    private String leader;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java
new file mode 100644
index 0000000..e38a8dd
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java
@@ -0,0 +1,76 @@
+package com.ruoyi.system.domain.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.common.excel.annotation.ExcelDictFormat;
+import com.ruoyi.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 鐢ㄦ埛瀵硅薄瀵煎叆VO
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+// @Accessors(chain = true) // 瀵煎叆涓嶅厑璁镐娇鐢� 浼氭壘涓嶅埌set鏂规硶
+public class SysUserImportVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鐢ㄦ埛ID
+     */
+    @ExcelProperty(value = "鐢ㄦ埛搴忓彿")
+    private Long userId;
+
+    /**
+     * 閮ㄩ棬ID
+     */
+    @ExcelProperty(value = "閮ㄩ棬缂栧彿")
+    private Long deptId;
+
+    /**
+     * 鐢ㄦ埛璐﹀彿
+     */
+    @ExcelProperty(value = "鐧诲綍鍚嶇О")
+    private String userName;
+
+    /**
+     * 鐢ㄦ埛鏄电О
+     */
+    @ExcelProperty(value = "鐢ㄦ埛鍚嶇О")
+    private String nickName;
+
+    /**
+     * 鐢ㄦ埛閭
+     */
+    @ExcelProperty(value = "鐢ㄦ埛閭")
+    private String email;
+
+    /**
+     * 鎵嬫満鍙风爜
+     */
+    @ExcelProperty(value = "鎵嬫満鍙风爜")
+    private String phonenumber;
+
+    /**
+     * 鐢ㄦ埛鎬у埆
+     */
+    @ExcelProperty(value = "鐢ㄦ埛鎬у埆", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_user_sex")
+    private String sex;
+
+    /**
+     * 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�
+     */
+    @ExcelProperty(value = "甯愬彿鐘舵��", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(dictType = "sys_normal_disable")
+    private String status;
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java
new file mode 100644
index 0000000..1990cf8
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java
@@ -0,0 +1,118 @@
+package com.ruoyi.system.listener;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.crypto.digest.BCrypt;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.ValidatorUtils;
+import com.ruoyi.common.excel.core.ExcelListener;
+import com.ruoyi.common.excel.core.ExcelResult;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.system.domain.vo.SysUserImportVo;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysUserService;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+/**
+ * 绯荤粺鐢ㄦ埛鑷畾涔夊鍏�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class SysUserImportListener extends AnalysisEventListener<SysUserImportVo> implements ExcelListener<SysUserImportVo> {
+
+    private final ISysUserService userService;
+
+    private final String password;
+
+    private final Boolean isUpdateSupport;
+
+    private final String operName;
+
+    private int successNum = 0;
+    private int failureNum = 0;
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+
+    public SysUserImportListener(Boolean isUpdateSupport) {
+        String initPassword = SpringUtils.getBean(ISysConfigService.class).selectConfigByKey("sys.user.initPassword");
+        this.userService = SpringUtils.getBean(ISysUserService.class);
+        this.password = BCrypt.hashpw(initPassword);
+        this.isUpdateSupport = isUpdateSupport;
+        this.operName = LoginHelper.getUsername();
+    }
+
+    @Override
+    public void invoke(SysUserImportVo userVo, AnalysisContext context) {
+        SysUser user = this.userService.selectUserByUserName(userVo.getUserName());
+        try {
+            // 楠岃瘉鏄惁瀛樺湪杩欎釜鐢ㄦ埛
+            if (ObjectUtil.isNull(user)) {
+                user = BeanUtil.toBean(userVo, SysUser.class);
+                ValidatorUtils.validate(user);
+                user.setPassword(password);
+                user.setCreateBy(operName);
+                userService.insertUser(user);
+                successNum++;
+                successMsg.append("<br/>").append(successNum).append("銆佽处鍙� ").append(user.getUserName()).append(" 瀵煎叆鎴愬姛");
+            } else if (isUpdateSupport) {
+                Long userId = user.getUserId();
+                user = BeanUtil.toBean(userVo, SysUser.class);
+                user.setUserId(userId);
+                ValidatorUtils.validate(user);
+                userService.checkUserAllowed(user);
+                userService.checkUserDataScope(user.getUserId());
+                user.setUpdateBy(operName);
+                userService.updateUser(user);
+                successNum++;
+                successMsg.append("<br/>").append(successNum).append("銆佽处鍙� ").append(user.getUserName()).append(" 鏇存柊鎴愬姛");
+            } else {
+                failureNum++;
+                failureMsg.append("<br/>").append(failureNum).append("銆佽处鍙� ").append(user.getUserName()).append(" 宸插瓨鍦�");
+            }
+        } catch (Exception e) {
+            failureNum++;
+            String msg = "<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆澶辫触锛�";
+            failureMsg.append(msg).append(e.getMessage());
+            log.error(msg, e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+
+    }
+
+    @Override
+    public ExcelResult<SysUserImportVo> getExcelResult() {
+        return new ExcelResult<SysUserImportVo>() {
+
+            @Override
+            public String getAnalysis() {
+                if (failureNum > 0) {
+                    failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細");
+                    throw new ServiceException(failureMsg.toString());
+                } else {
+                    successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�");
+                }
+                return successMsg.toString();
+            }
+
+            @Override
+            public List<SysUserImportVo> getList() {
+                return null;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return null;
+            }
+        };
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
new file mode 100644
index 0000000..52fa701
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysConfig;
+
+/**
+ * 鍙傛暟閰嶇疆 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysConfigMapper extends BaseMapperPlus<SysConfigMapper, SysConfig, SysConfig> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
new file mode 100644
index 0000000..80de8c5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.ruoyi.common.mybatis.annotation.DataColumn;
+import com.ruoyi.common.mybatis.annotation.DataPermission;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysDept;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 閮ㄩ棬绠$悊 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysDeptMapper extends BaseMapperPlus<SysDeptMapper, SysDept, SysDept> {
+
+    /**
+     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+     *
+     * @param queryWrapper 鏌ヨ鏉′欢
+     * @return 閮ㄩ棬淇℃伅闆嗗悎
+     */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "dept_id")
+    })
+    List<SysDept> selectDeptList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+     *
+     * @param roleId            瑙掕壊ID
+     * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+     * @return 閫変腑閮ㄩ棬鍒楄〃
+     */
+    List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
new file mode 100644
index 0000000..d98baca
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.system.domain.SysDictData;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+
+import java.util.List;
+
+/**
+ * 瀛楀吀琛� 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysDictDataMapper extends BaseMapperPlus<SysDictDataMapper, SysDictData, SysDictData> {
+
+    default List<SysDictData> selectDictDataByType(String dictType) {
+        return selectList(
+            new LambdaQueryWrapper<SysDictData>()
+                .eq(SysDictData::getStatus, UserConstants.DICT_NORMAL)
+                .eq(SysDictData::getDictType, dictType)
+                .orderByAsc(SysDictData::getDictSort));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
new file mode 100644
index 0000000..981a715
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.system.domain.SysDictType;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 瀛楀吀琛� 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysDictTypeMapper extends BaseMapperPlus<SysDictTypeMapper, SysDictType, SysDictType> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
new file mode 100644
index 0000000..06c6eff
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysLogininfor;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysLogininforMapper extends BaseMapperPlus<SysLogininforMapper, SysLogininfor, SysLogininfor> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
new file mode 100644
index 0000000..366115a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
@@ -0,0 +1,82 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.system.domain.SysMenu;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 鑿滃崟琛� 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, SysMenu> {
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鎵�鏈夋潈闄�
+     *
+     * @return 鏉冮檺鍒楄〃
+     */
+    List<String> selectMenuPerms();
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     *
+     * @param queryWrapper 鏌ヨ鏉′欢
+     * @return 鑿滃崟鍒楄〃
+     */
+    List<SysMenu> selectMenuListByUserId(@Param(Constants.WRAPPER) Wrapper<SysMenu> queryWrapper);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    List<String> selectMenuPermsByUserId(Long userId);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    List<String> selectMenuPermsByRoleId(Long roleId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+     *
+     * @return 鑿滃崟鍒楄〃
+     */
+    default List<SysMenu> selectMenuTreeAll() {
+        LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<SysMenu>()
+            .in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU)
+            .eq(SysMenu::getStatus, UserConstants.MENU_NORMAL)
+            .orderByAsc(SysMenu::getParentId)
+            .orderByAsc(SysMenu::getOrderNum);
+        return this.selectList(lqw);
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    List<SysMenu> selectMenuTreeByUserId(Long userId);
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+     *
+     * @param roleId            瑙掕壊ID
+     * @param menuCheckStrictly 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+     * @return 閫変腑鑿滃崟鍒楄〃
+     */
+    List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
new file mode 100644
index 0000000..119be77
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysNotice;
+
+/**
+ * 閫氱煡鍏憡琛� 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysNoticeMapper extends BaseMapperPlus<SysNoticeMapper, SysNotice, SysNotice> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
new file mode 100644
index 0000000..ae719ea
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysOperLogMapper extends BaseMapperPlus<SysOperLogMapper, SysOperLog, SysOperLog> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java
new file mode 100644
index 0000000..2429e49
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java
@@ -0,0 +1,16 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysOssConfig;
+import com.ruoyi.system.domain.vo.SysOssConfigVo;
+
+/**
+ * 瀵硅薄瀛樺偍閰嶇疆Mapper鎺ュ彛
+ *
+ * @author Lion Li
+ * @author 瀛よ垷鐑熼洦
+ * @date 2021-08-13
+ */
+public interface SysOssConfigMapper extends BaseMapperPlus<SysOssConfigMapper, SysOssConfig, SysOssConfigVo> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java
new file mode 100644
index 0000000..83b6217
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysOss;
+import com.ruoyi.system.domain.vo.SysOssVo;
+
+/**
+ * 鏂囦欢涓婁紶 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysOssMapper extends BaseMapperPlus<SysOssMapper, SysOss, SysOssVo> {
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
new file mode 100644
index 0000000..7cf6b53
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
@@ -0,0 +1,31 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysPost;
+
+import java.util.List;
+
+/**
+ * 宀椾綅淇℃伅 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysPostMapper extends BaseMapperPlus<SysPostMapper, SysPost, SysPost> {
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑宀椾綅ID鍒楄〃
+     */
+    List<Long> selectPostListByUserId(Long userId);
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    List<SysPost> selectPostsByUserName(String userName);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
new file mode 100644
index 0000000..7cb33f0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysRoleDept;
+
+/**
+ * 瑙掕壊涓庨儴闂ㄥ叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysRoleDeptMapper extends BaseMapperPlus<SysRoleDeptMapper, SysRoleDept, SysRoleDept> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
new file mode 100644
index 0000000..84e38f0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
@@ -0,0 +1,62 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.mybatis.annotation.DataColumn;
+import com.ruoyi.common.mybatis.annotation.DataPermission;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 瑙掕壊琛� 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysRoleMapper extends BaseMapperPlus<SysRoleMapper, SysRole, SysRole> {
+
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id")
+    })
+    Page<SysRole> selectPageRoleList(@Param("page") Page<SysRole> page, @Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+     *
+     * @param queryWrapper 鏌ヨ鏉′欢
+     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+     */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id")
+    })
+    List<SysRole> selectRoleList(@Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 瑙掕壊鍒楄〃
+     */
+    List<SysRole> selectRolePermissionByUserId(Long userId);
+
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑瑙掕壊ID鍒楄〃
+     */
+    List<Long> selectRoleListByUserId(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 瑙掕壊鍒楄〃
+     */
+    List<SysRole> selectRolesByUserName(String userName);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
new file mode 100644
index 0000000..c4e5983
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysRoleMenu;
+
+/**
+ * 瑙掕壊涓庤彍鍗曞叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysRoleMenuMapper extends BaseMapperPlus<SysRoleMenuMapper, SysRoleMenu, SysRoleMenu> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
new file mode 100644
index 0000000..48713c7
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -0,0 +1,87 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.mybatis.annotation.DataColumn;
+import com.ruoyi.common.mybatis.annotation.DataPermission;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 鐢ㄦ埛琛� 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysUserMapper extends BaseMapperPlus<SysUserMapper, SysUser, SysUser> {
+
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id"),
+        @DataColumn(key = "userName", value = "u.user_id")
+    })
+    Page<SysUser> selectPageUserList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+     *
+     * @param queryWrapper 鏌ヨ鏉′欢
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id"),
+        @DataColumn(key = "userName", value = "u.user_id")
+    })
+    List<SysUser> selectUserList(@Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸查厤鐢ㄦ埛瑙掕壊鍒楄〃
+     *
+     * @param queryWrapper 鏌ヨ鏉′欢
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id"),
+        @DataColumn(key = "userName", value = "u.user_id")
+    })
+    Page<SysUser> selectAllocatedList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     *
+     * @param queryWrapper 鏌ヨ鏉′欢
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id"),
+        @DataColumn(key = "userName", value = "u.user_id")
+    })
+    Page<SysUser> selectUnallocatedList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    SysUser selectUserByUserName(String userName);
+
+    /**
+     * 閫氳繃鎵嬫満鍙锋煡璇㈢敤鎴�
+     *
+     * @param phonenumber 鎵嬫満鍙�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    SysUser selectUserByPhonenumber(String phonenumber);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    SysUser selectUserById(Long userId);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
new file mode 100644
index 0000000..9550eb0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysUserPost;
+
+/**
+ * 鐢ㄦ埛涓庡矖浣嶅叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysUserPostMapper extends BaseMapperPlus<SysUserPostMapper, SysUserPost, SysUserPost> {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
new file mode 100644
index 0000000..0970914
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.mapper;
+
+import com.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
+import com.ruoyi.system.domain.SysUserRole;
+
+import java.util.List;
+
+/**
+ * 鐢ㄦ埛涓庤鑹插叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author Lion Li
+ */
+public interface SysUserRoleMapper extends BaseMapperPlus<SysUserRoleMapper, SysUserRole, SysUserRole> {
+
+    List<Long> selectUserIdsByRoleId(Long roleId);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java
new file mode 100644
index 0000000..36ed651
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java
@@ -0,0 +1,41 @@
+package com.ruoyi.system.runner;
+
+import com.ruoyi.common.core.config.RuoYiConfig;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysDictTypeService;
+import com.ruoyi.system.service.ISysOssConfigService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鍒濆鍖� system 妯″潡瀵瑰簲涓氬姟鏁版嵁
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Component
+public class SystemApplicationRunner implements ApplicationRunner {
+
+    private final RuoYiConfig ruoyiConfig;
+    private final ISysConfigService configService;
+    private final ISysDictTypeService dictTypeService;
+    private final ISysOssConfigService ossConfigService;
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        ossConfigService.init();
+        log.info("鍒濆鍖朞SS閰嶇疆鎴愬姛");
+        if (ruoyiConfig.isCacheLazy()) {
+            return;
+        }
+        configService.loadingConfigCache();
+        log.info("鍔犺浇鍙傛暟缂撳瓨鏁版嵁鎴愬姛");
+        dictTypeService.loadingDictCache();
+        log.info("鍔犺浇瀛楀吀缂撳瓨鏁版嵁鎴愬姛");
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
new file mode 100644
index 0000000..83889b9
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -0,0 +1,96 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysConfig;
+
+import java.util.List;
+
+/**
+ * 鍙傛暟閰嶇疆 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysConfigService {
+
+
+    TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     *
+     * @param configId 鍙傛暟閰嶇疆ID
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    SysConfig selectConfigById(Long configId);
+
+    /**
+     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     *
+     * @param configKey 鍙傛暟閿悕
+     * @return 鍙傛暟閿��
+     */
+    String selectConfigByKey(String configKey);
+
+    /**
+     * 鑾峰彇楠岃瘉鐮佸紑鍏�
+     *
+     * @return true寮�鍚紝false鍏抽棴
+     */
+    boolean selectCaptchaEnabled();
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 鍙傛暟閰嶇疆闆嗗悎
+     */
+    List<SysConfig> selectConfigList(SysConfig config);
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    String insertConfig(SysConfig config);
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    String updateConfig(SysConfig config);
+
+    /**
+     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+     *
+     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+     */
+    void deleteConfigByIds(Long[] configIds);
+
+    /**
+     * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
+     */
+    void loadingConfigCache();
+
+    /**
+     * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
+     */
+    void clearConfigCache();
+
+    /**
+     * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
+     */
+    void resetConfigCache();
+
+    /**
+     * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
+     *
+     * @param config 鍙傛暟淇℃伅
+     * @return 缁撴灉
+     */
+    String checkConfigKeyUnique(SysConfig config);
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataScopeService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataScopeService.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataScopeService.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDataScopeService.java
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
new file mode 100644
index 0000000..14f521b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
@@ -0,0 +1,66 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.system.domain.SysDictData;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+
+import java.util.List;
+
+/**
+ * 瀛楀吀 涓氬姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysDictDataService {
+
+
+    TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData, PageQuery pageQuery);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+     *
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    List<SysDictData> selectDictDataList(SysDictData dictData);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+     *
+     * @param dictType  瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀閿��
+     * @return 瀛楀吀鏍囩
+     */
+    String selectDictLabel(String dictType, String dictValue);
+
+    /**
+     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+     *
+     * @param dictCode 瀛楀吀鏁版嵁ID
+     * @return 瀛楀吀鏁版嵁
+     */
+    SysDictData selectDictDataById(Long dictCode);
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+     */
+    void deleteDictDataByIds(Long[] dictCodes);
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    List<SysDictData> insertDictData(SysDictData dictData);
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    List<SysDictData> updateDictData(SysDictData dictData);
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
new file mode 100644
index 0000000..ae78363
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
@@ -0,0 +1,104 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.system.domain.SysDictData;
+import com.ruoyi.system.domain.SysDictType;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+
+import java.util.List;
+
+/**
+ * 瀛楀吀 涓氬姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysDictTypeService {
+
+
+    TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+     *
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    List<SysDictType> selectDictTypeList(SysDictType dictType);
+
+    /**
+     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+     *
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    List<SysDictType> selectDictTypeAll();
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    List<SysDictData> selectDictDataByType(String dictType);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+     *
+     * @param dictId 瀛楀吀绫诲瀷ID
+     * @return 瀛楀吀绫诲瀷
+     */
+    SysDictType selectDictTypeById(Long dictId);
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀绫诲瀷
+     */
+    SysDictType selectDictTypeByType(String dictType);
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀淇℃伅
+     *
+     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+     */
+    void deleteDictTypeByIds(Long[] dictIds);
+
+    /**
+     * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
+     */
+    void loadingDictCache();
+
+    /**
+     * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
+     */
+    void clearDictCache();
+
+    /**
+     * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
+     */
+    void resetDictCache();
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     *
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    List<SysDictData> insertDictType(SysDictType dictType);
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     *
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    List<SysDictData> updateDictType(SysDictType dictType);
+
+    /**
+     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 缁撴灉
+     */
+    String checkDictTypeUnique(SysDictType dictType);
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
new file mode 100644
index 0000000..d67dfe4
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysLogininfor;
+
+import java.util.List;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysLogininforService {
+
+
+    TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery);
+
+    /**
+     * 鏂板绯荤粺鐧诲綍鏃ュ織
+     *
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     */
+    void insertLogininfor(SysLogininfor logininfor);
+
+    /**
+     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+     *
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     * @return 鐧诲綍璁板綍闆嗗悎
+     */
+    List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+     *
+     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+     * @return 缁撴灉
+     */
+    int deleteLogininforByIds(Long[] infoIds);
+
+    /**
+     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+     */
+    void cleanLogininfor();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
new file mode 100644
index 0000000..4e69042
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
@@ -0,0 +1,66 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysNotice;
+
+import java.util.List;
+
+/**
+ * 鍏憡 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysNoticeService {
+
+
+    TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ鍏憡淇℃伅
+     *
+     * @param noticeId 鍏憡ID
+     * @return 鍏憡淇℃伅
+     */
+    SysNotice selectNoticeById(Long noticeId);
+
+    /**
+     * 鏌ヨ鍏憡鍒楄〃
+     *
+     * @param notice 鍏憡淇℃伅
+     * @return 鍏憡闆嗗悎
+     */
+    List<SysNotice> selectNoticeList(SysNotice notice);
+
+    /**
+     * 鏂板鍏憡
+     *
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    int insertNotice(SysNotice notice);
+
+    /**
+     * 淇敼鍏憡
+     *
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    int updateNotice(SysNotice notice);
+
+    /**
+     * 鍒犻櫎鍏憡淇℃伅
+     *
+     * @param noticeId 鍏憡ID
+     * @return 缁撴灉
+     */
+    int deleteNoticeById(Long noticeId);
+
+    /**
+     * 鎵归噺鍒犻櫎鍏憡淇℃伅
+     *
+     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+     * @return 缁撴灉
+     */
+    int deleteNoticeByIds(Long[] noticeIds);
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
new file mode 100644
index 0000000..72e4fe5
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
@@ -0,0 +1,53 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysOperLog;
+
+import java.util.List;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysOperLogService {
+
+    TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog, PageQuery pageQuery);
+
+    /**
+     * 鏂板鎿嶄綔鏃ュ織
+     *
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    void insertOperlog(SysOperLog operLog);
+
+    /**
+     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+     *
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     * @return 鎿嶄綔鏃ュ織闆嗗悎
+     */
+    List<SysOperLog> selectOperLogList(SysOperLog operLog);
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+     *
+     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+     * @return 缁撴灉
+     */
+    int deleteOperLogByIds(Long[] operIds);
+
+    /**
+     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+     *
+     * @param operId 鎿嶄綔ID
+     * @return 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    SysOperLog selectOperLogById(Long operId);
+
+    /**
+     * 娓呯┖鎿嶄綔鏃ュ織
+     */
+    void cleanOperLog();
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java
new file mode 100644
index 0000000..f38af83
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java
@@ -0,0 +1,65 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.bo.SysOssConfigBo;
+import com.ruoyi.system.domain.vo.SysOssConfigVo;
+
+import java.util.Collection;
+
+/**
+ * 瀵硅薄瀛樺偍閰嶇疆Service鎺ュ彛
+ *
+ * @author Lion Li
+ * @author 瀛よ垷鐑熼洦
+ * @date 2021-08-13
+ */
+public interface ISysOssConfigService {
+
+    /**
+     * 鍒濆鍖朞SS閰嶇疆
+     */
+    void init();
+
+    /**
+     * 鏌ヨ鍗曚釜
+     */
+    SysOssConfigVo queryById(Long ossConfigId);
+
+    /**
+     * 鏌ヨ鍒楄〃
+     */
+    TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery);
+
+
+    /**
+     * 鏍规嵁鏂板涓氬姟瀵硅薄鎻掑叆瀵硅薄瀛樺偍閰嶇疆
+     *
+     * @param bo 瀵硅薄瀛樺偍閰嶇疆鏂板涓氬姟瀵硅薄
+     * @return
+     */
+    Boolean insertByBo(SysOssConfigBo bo);
+
+    /**
+     * 鏍规嵁缂栬緫涓氬姟瀵硅薄淇敼瀵硅薄瀛樺偍閰嶇疆
+     *
+     * @param bo 瀵硅薄瀛樺偍閰嶇疆缂栬緫涓氬姟瀵硅薄
+     * @return
+     */
+    Boolean updateByBo(SysOssConfigBo bo);
+
+    /**
+     * 鏍¢獙骞跺垹闄ゆ暟鎹�
+     *
+     * @param ids     涓婚敭闆嗗悎
+     * @param isValid 鏄惁鏍¢獙,true-鍒犻櫎鍓嶆牎楠�,false-涓嶆牎楠�
+     * @return
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 鍚敤鍋滅敤鐘舵��
+     */
+    int updateOssConfigStatus(SysOssConfigBo bo);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
new file mode 100644
index 0000000..7d518af
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
@@ -0,0 +1,34 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysOss;
+import com.ruoyi.system.domain.bo.SysOssBo;
+import com.ruoyi.system.domain.vo.SysOssVo;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 鏂囦欢涓婁紶 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysOssService {
+
+    TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
+
+    List<SysOssVo> listByIds(Collection<Long> ossIds);
+
+    SysOssVo getById(Long ossId);
+
+    SysOssVo upload(MultipartFile file);
+
+    void download(Long ossId, HttpServletResponse response) throws IOException;
+
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
new file mode 100644
index 0000000..0fbbe02
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
@@ -0,0 +1,105 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysPost;
+
+import java.util.List;
+
+/**
+ * 宀椾綅淇℃伅 鏈嶅姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysPostService {
+
+
+    TableDataInfo<SysPost> selectPagePostList(SysPost post, PageQuery pageQuery);
+
+    /**
+     * 鏌ヨ宀椾綅淇℃伅闆嗗悎
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 宀椾綅鍒楄〃
+     */
+    List<SysPost> selectPostList(SysPost post);
+
+    /**
+     * 鏌ヨ鎵�鏈夊矖浣�
+     *
+     * @return 宀椾綅鍒楄〃
+     */
+    List<SysPost> selectPostAll();
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+     *
+     * @param postId 宀椾綅ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    SysPost selectPostById(Long postId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑宀椾綅ID鍒楄〃
+     */
+    List<Long> selectPostListByUserId(Long userId);
+
+    /**
+     * 鏍¢獙宀椾綅鍚嶇О
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    String checkPostNameUnique(SysPost post);
+
+    /**
+     * 鏍¢獙宀椾綅缂栫爜
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    String checkPostCodeUnique(SysPost post);
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+     *
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    long countUserPostById(Long postId);
+
+    /**
+     * 鍒犻櫎宀椾綅淇℃伅
+     *
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    int deletePostById(Long postId);
+
+    /**
+     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+     *
+     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+     * @return 缁撴灉
+     */
+    int deletePostByIds(Long[] postIds);
+
+    /**
+     * 鏂板淇濆瓨宀椾綅淇℃伅
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    int insertPost(SysPost post);
+
+    /**
+     * 淇敼淇濆瓨宀椾綅淇℃伅
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    int updatePost(SysPost post);
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
new file mode 100644
index 0000000..c03be2c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
@@ -0,0 +1,179 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysUserRole;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 瑙掕壊涓氬姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysRoleService {
+
+
+    TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+     */
+    List<SysRole> selectRoleList(SysRole role);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鍒楄〃
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 瑙掕壊鍒楄〃
+     */
+    List<SysRole> selectRolesByUserId(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鏉冮檺
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    Set<String> selectRolePermissionByUserId(Long userId);
+
+    /**
+     * 鏌ヨ鎵�鏈夎鑹�
+     *
+     * @return 瑙掕壊鍒楄〃
+     */
+    List<SysRole> selectRoleAll();
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑瑙掕壊ID鍒楄〃
+     */
+    List<Long> selectRoleListByUserId(Long userId);
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    SysRole selectRoleById(Long roleId);
+
+    /**
+     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    String checkRoleNameUnique(SysRole role);
+
+    /**
+     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    String checkRoleKeyUnique(SysRole role);
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
+     *
+     * @param role 瑙掕壊淇℃伅
+     */
+    void checkRoleAllowed(SysRole role);
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
+     *
+     * @param roleId 瑙掕壊id
+     */
+    void checkRoleDataScope(Long roleId);
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    long countUserRoleByRoleId(Long roleId);
+
+    /**
+     * 鏂板淇濆瓨瑙掕壊淇℃伅
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    int insertRole(SysRole role);
+
+    /**
+     * 淇敼淇濆瓨瑙掕壊淇℃伅
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    int updateRole(SysRole role);
+
+    /**
+     * 淇敼瑙掕壊鐘舵��
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    int updateRoleStatus(SysRole role);
+
+    /**
+     * 淇敼鏁版嵁鏉冮檺淇℃伅
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    int authDataScope(SysRole role);
+
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    int deleteRoleById(Long roleId);
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+     *
+     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+     * @return 缁撴灉
+     */
+    int deleteRoleByIds(Long[] roleIds);
+
+    /**
+     * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     *
+     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+     * @return 缁撴灉
+     */
+    int deleteAuthUser(SysUserRole userRole);
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     *
+     * @param roleId  瑙掕壊ID
+     * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    int deleteAuthUsers(Long roleId, Long[] userIds);
+
+    /**
+     * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
+     *
+     * @param roleId  瑙掕壊ID
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    int insertAuthUsers(Long roleId, Long[] userIds);
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
new file mode 100644
index 0000000..8f393e6
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -0,0 +1,211 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.system.domain.SysUser;
+
+import java.util.List;
+
+/**
+ * 鐢ㄦ埛 涓氬姟灞�
+ *
+ * @author Lion Li
+ */
+public interface ISysUserService {
+
+
+    TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    List<SysUser> selectUserList(SysUser user);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery);
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery);
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    SysUser selectUserByUserName(String userName);
+
+    /**
+     * 閫氳繃鎵嬫満鍙锋煡璇㈢敤鎴�
+     *
+     * @param phonenumber 鎵嬫満鍙�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    SysUser selectUserByPhonenumber(String phonenumber);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    SysUser selectUserById(Long userId);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    String selectUserRoleGroup(String userName);
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    String selectUserPostGroup(String userName);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    String checkUserNameUnique(SysUser user);
+
+    /**
+     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    String checkPhoneUnique(SysUser user);
+
+    /**
+     * 鏍¢獙email鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    String checkEmailUnique(SysUser user);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     */
+    void checkUserAllowed(SysUser user);
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
+     *
+     * @param userId 鐢ㄦ埛id
+     */
+    void checkUserDataScope(Long userId);
+
+    /**
+     * 鏂板鐢ㄦ埛淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    int insertUser(SysUser user);
+
+    /**
+     * 娉ㄥ唽鐢ㄦ埛淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    boolean registerUser(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    int updateUser(SysUser user);
+
+    /**
+     * 鐢ㄦ埛鎺堟潈瑙掕壊
+     *
+     * @param userId  鐢ㄦ埛ID
+     * @param roleIds 瑙掕壊缁�
+     */
+    void insertUserAuth(Long userId, Long[] roleIds);
+
+    /**
+     * 淇敼鐢ㄦ埛鐘舵��
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    int updateUserStatus(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    int updateUserProfile(SysUser user);
+
+    /**
+     * 淇敼鐢ㄦ埛澶村儚
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @param avatar   澶村儚鍦板潃
+     * @return 缁撴灉
+     */
+    boolean updateUserAvatar(String userName, String avatar);
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    int resetPwd(SysUser user);
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @return 缁撴灉
+     */
+    int resetUserPwd(String userName, String password);
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    int deleteUserById(Long userId);
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+     *
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    int deleteUserByIds(Long[] userIds);
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
new file mode 100644
index 0000000..b5b072b
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
@@ -0,0 +1,294 @@
+package com.ruoyi.system.service;
+
+import cn.dev33.satoken.exception.NotLoginException;
+import cn.dev33.satoken.secure.BCrypt;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.log.event.LogininforEvent;
+import com.ruoyi.common.core.domain.dto.RoleDTO;
+import com.ruoyi.common.core.enums.DeviceType;
+import com.ruoyi.common.core.enums.LoginType;
+import com.ruoyi.common.core.enums.UserStatus;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.domain.model.XcxLoginUser;
+import com.ruoyi.common.core.exception.user.CaptchaException;
+import com.ruoyi.common.core.exception.user.CaptchaExpireException;
+import com.ruoyi.common.core.exception.user.UserException;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.system.mapper.SysUserMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.time.Duration;
+import java.util.List;
+import java.util.function.Supplier;
+
+/**
+ * 鐧诲綍鏍¢獙鏂规硶
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Slf4j
+@Service
+public class SysLoginService {
+
+    private final SysUserMapper userMapper;
+    private final ISysConfigService configService;
+    private final SysPermissionService permissionService;
+
+    @Value("${user.password.maxRetryCount}")
+    private Integer maxRetryCount;
+
+    @Value("${user.password.lockTime}")
+    private Integer lockTime;
+
+    /**
+     * 鐧诲綍楠岃瘉
+     *
+     * @param username 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @param code     楠岃瘉鐮�
+     * @param uuid     鍞竴鏍囪瘑
+     * @return 缁撴灉
+     */
+    public String login(String username, String password, String code, String uuid) {
+        HttpServletRequest request = ServletUtils.getRequest();
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        // 楠岃瘉鐮佸紑鍏�
+        if (captchaEnabled) {
+            validateCaptcha(username, code, uuid, request);
+        }
+        SysUser user = loadUserByUsername(username);
+        checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
+        // 姝ゅ鍙牴鎹櫥褰曠敤鎴风殑鏁版嵁涓嶅悓 鑷鍒涘缓 loginUser
+        LoginUser loginUser = buildLoginUser(user);
+        // 鐢熸垚token
+        LoginHelper.loginByDevice(loginUser, DeviceType.PC);
+
+        recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId(), username);
+        return StpUtil.getTokenValue();
+    }
+
+    public String smsLogin(String phonenumber, String smsCode) {
+        // 閫氳繃鎵嬫満鍙锋煡鎵剧敤鎴�
+        SysUser user = loadUserByPhonenumber(phonenumber);
+
+        checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode));
+        // 姝ゅ鍙牴鎹櫥褰曠敤鎴风殑鏁版嵁涓嶅悓 鑷鍒涘缓 loginUser
+        LoginUser loginUser = buildLoginUser(user);
+        // 鐢熸垚token
+        LoginHelper.loginByDevice(loginUser, DeviceType.APP);
+
+        recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId(), user.getUserName());
+        return StpUtil.getTokenValue();
+    }
+
+
+    public String xcxLogin(String xcxCode) {
+        // xcxCode 涓� 灏忕▼搴忚皟鐢� wx.login 鎺堟潈鍚庤幏鍙�
+        // todo 浠ヤ笅鑷瀹炵幇
+        // 鏍¢獙 appid + appsrcret + xcxCode 璋冪敤鐧诲綍鍑瘉鏍¢獙鎺ュ彛 鑾峰彇 session_key 涓� openid
+        String openid = "";
+        SysUser user = loadUserByOpenid(openid);
+
+        // 姝ゅ鍙牴鎹櫥褰曠敤鎴风殑鏁版嵁涓嶅悓 鑷鍒涘缓 loginUser
+        XcxLoginUser loginUser = new XcxLoginUser();
+        loginUser.setUserId(user.getUserId());
+        loginUser.setUsername(user.getUserName());
+        loginUser.setUserType(user.getUserType());
+        loginUser.setOpenid(openid);
+        // 鐢熸垚token
+        LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
+
+        recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+        recordLoginInfo(user.getUserId(), user.getUserName());
+        return StpUtil.getTokenValue();
+    }
+
+    /**
+     * 閫�鍑虹櫥褰�
+     */
+    public void logout() {
+        try {
+            LoginUser loginUser = LoginHelper.getLoginUser();
+            StpUtil.logout();
+            recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
+        } catch (NotLoginException ignored) {
+        }
+    }
+
+    /**
+     * 璁板綍鐧诲綍淇℃伅
+     *
+     * @param username 鐢ㄦ埛鍚�
+     * @param status   鐘舵��
+     * @param message  娑堟伅鍐呭
+     * @return
+     */
+    private void recordLogininfor(String username, String status, String message) {
+        LogininforEvent logininforEvent = new LogininforEvent();
+        logininforEvent.setUsername(username);
+        logininforEvent.setStatus(status);
+        logininforEvent.setMessage(message);
+        logininforEvent.setRequest(ServletUtils.getRequest());
+        SpringUtils.context().publishEvent(logininforEvent);
+    }
+
+    /**
+     * 鏍¢獙鐭俊楠岃瘉鐮�
+     */
+    private boolean validateSmsCode(String phonenumber, String smsCode) {
+        String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
+        if (StringUtils.isBlank(code)) {
+            recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        return code.equals(smsCode);
+    }
+
+    /**
+     * 鏍¢獙楠岃瘉鐮�
+     *
+     * @param username 鐢ㄦ埛鍚�
+     * @param code     楠岃瘉鐮�
+     * @param uuid     鍞竴鏍囪瘑
+     */
+    public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
+        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
+        String captcha = RedisUtils.getCacheObject(verifyKey);
+        RedisUtils.deleteObject(verifyKey);
+        if (captcha == null) {
+            recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        if (!code.equalsIgnoreCase(captcha)) {
+            recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
+            throw new CaptchaException();
+        }
+    }
+
+    private SysUser loadUserByUsername(String username) {
+        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+            .select(SysUser::getUserName, SysUser::getStatus)
+            .eq(SysUser::getUserName, username));
+        if (ObjectUtil.isNull(user)) {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", username);
+            throw new UserException("user.not.exists", username);
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", username);
+            throw new UserException("user.blocked", username);
+        }
+        return userMapper.selectUserByUserName(username);
+    }
+
+    private SysUser loadUserByPhonenumber(String phonenumber) {
+        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+            .select(SysUser::getPhonenumber, SysUser::getStatus)
+            .eq(SysUser::getPhonenumber, phonenumber));
+        if (ObjectUtil.isNull(user)) {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", phonenumber);
+            throw new UserException("user.not.exists", phonenumber);
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", phonenumber);
+            throw new UserException("user.blocked", phonenumber);
+        }
+        return userMapper.selectUserByPhonenumber(phonenumber);
+    }
+
+    private SysUser loadUserByOpenid(String openid) {
+        // 浣跨敤 openid 鏌ヨ缁戝畾鐢ㄦ埛 濡傛湭缁戝畾鐢ㄦ埛 鍒欐牴鎹笟鍔¤嚜琛屽鐞� 渚嬪 鍒涘缓榛樿鐢ㄦ埛
+        // todo 鑷瀹炵幇 userService.selectUserByOpenid(openid);
+        SysUser user = new SysUser();
+        if (ObjectUtil.isNull(user)) {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", openid);
+            // todo 鐢ㄦ埛涓嶅瓨鍦� 涓氬姟閫昏緫鑷瀹炵幇
+        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", openid);
+            // todo 鐢ㄦ埛宸茶鍋滅敤 涓氬姟閫昏緫鑷瀹炵幇
+        }
+        return user;
+    }
+
+    /**
+     * 鏋勫缓鐧诲綍鐢ㄦ埛
+     */
+    private LoginUser buildLoginUser(SysUser user) {
+        LoginUser loginUser = new LoginUser();
+        loginUser.setUserId(user.getUserId());
+        loginUser.setDeptId(user.getDeptId());
+        loginUser.setUsername(user.getUserName());
+        loginUser.setUserType(user.getUserType());
+        loginUser.setMenuPermission(permissionService.getMenuPermission(user));
+        loginUser.setRolePermission(permissionService.getRolePermission(user));
+        loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
+        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
+        loginUser.setRoles(roles);
+        return loginUser;
+    }
+
+    /**
+     * 璁板綍鐧诲綍淇℃伅
+     *
+     * @param userId 鐢ㄦ埛ID
+     */
+    public void recordLoginInfo(Long userId, String username) {
+        SysUser sysUser = new SysUser();
+        sysUser.setUserId(userId);
+        sysUser.setLoginIp(ServletUtils.getClientIP());
+        sysUser.setLoginDate(DateUtils.getNowDate());
+        sysUser.setUpdateBy(username);
+        userMapper.updateById(sysUser);
+    }
+
+    /**
+     * 鐧诲綍鏍¢獙
+     */
+    private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
+        String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
+        String loginFail = Constants.LOGIN_FAIL;
+
+        // 鑾峰彇鐢ㄦ埛鐧诲綍閿欒娆℃暟(鍙嚜瀹氫箟闄愬埗绛栫暐 渚嬪: key + username + ip)
+        Integer errorNumber = RedisUtils.getCacheObject(errorKey);
+        // 閿佸畾鏃堕棿鍐呯櫥褰� 鍒欒涪鍑�
+        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
+            recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
+            throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
+        }
+
+        if (supplier.get()) {
+            // 鏄惁绗竴娆�
+            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
+            // 杈惧埌瑙勫畾閿欒娆℃暟 鍒欓攣瀹氱櫥褰�
+            if (errorNumber.equals(maxRetryCount)) {
+                RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
+                recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
+                throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
+            } else {
+                // 鏈揪鍒拌瀹氶敊璇鏁� 鍒欓�掑
+                RedisUtils.setCacheObject(errorKey, errorNumber);
+                recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
+                throw new UserException(loginType.getRetryLimitCount(), errorNumber);
+            }
+        }
+
+        // 鐧诲綍鎴愬姛 娓呯┖閿欒娆℃暟
+        RedisUtils.deleteObject(errorKey);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java
similarity index 100%
rename from ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java
rename to ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java
new file mode 100644
index 0000000..6a78c17
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java
@@ -0,0 +1,106 @@
+package com.ruoyi.system.service;
+
+import cn.dev33.satoken.secure.BCrypt;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.log.event.LogininforEvent;
+import com.ruoyi.common.core.enums.UserType;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.core.domain.model.RegisterBody;
+import com.ruoyi.common.core.exception.user.CaptchaException;
+import com.ruoyi.common.core.exception.user.CaptchaExpireException;
+import com.ruoyi.common.core.exception.user.UserException;
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import jakarta.servlet.http.HttpServletRequest;
+
+/**
+ * 娉ㄥ唽鏍¢獙鏂规硶
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysRegisterService {
+
+    private final ISysUserService userService;
+    private final ISysConfigService configService;
+
+    /**
+     * 娉ㄥ唽
+     */
+    public void register(RegisterBody registerBody) {
+        HttpServletRequest request = ServletUtils.getRequest();
+        String username = registerBody.getUsername();
+        String password = registerBody.getPassword();
+        // 鏍¢獙鐢ㄦ埛绫诲瀷鏄惁瀛樺湪
+        String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
+
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        // 楠岃瘉鐮佸紑鍏�
+        if (captchaEnabled) {
+            validateCaptcha(username, registerBody.getCode(), registerBody.getUuid(), request);
+        }
+        SysUser sysUser = new SysUser();
+        sysUser.setUserName(username);
+        sysUser.setNickName(username);
+        sysUser.setPassword(BCrypt.hashpw(password));
+        sysUser.setUserType(userType);
+
+        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) {
+            throw new UserException("user.register.save.error", username);
+        }
+        boolean regFlag = userService.registerUser(sysUser);
+        if (!regFlag) {
+            throw new UserException("user.register.error");
+        }
+        recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
+    }
+
+    /**
+     * 鏍¢獙楠岃瘉鐮�
+     *
+     * @param username 鐢ㄦ埛鍚�
+     * @param code     楠岃瘉鐮�
+     * @param uuid     鍞竴鏍囪瘑
+     * @return 缁撴灉
+     */
+    public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
+        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
+        String captcha = RedisUtils.getCacheObject(verifyKey);
+        RedisUtils.deleteObject(verifyKey);
+        if (captcha == null) {
+            recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
+            throw new CaptchaExpireException();
+        }
+        if (!code.equalsIgnoreCase(captcha)) {
+            recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
+            throw new CaptchaException();
+        }
+    }
+
+    /**
+     * 璁板綍鐧诲綍淇℃伅
+     *
+     * @param username 鐢ㄦ埛鍚�
+     * @param status   鐘舵��
+     * @param message  娑堟伅鍐呭
+     * @return
+     */
+    private void recordLogininfor(String username, String status, String message) {
+        LogininforEvent logininforEvent = new LogininforEvent();
+        logininforEvent.setUsername(username);
+        logininforEvent.setStatus(status);
+        logininforEvent.setMessage(message);
+        logininforEvent.setRequest(ServletUtils.getRequest());
+        SpringUtils.context().publishEvent(logininforEvent);
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
new file mode 100644
index 0000000..39b3cf0
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -0,0 +1,227 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.service.ConfigService;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.system.domain.SysConfig;
+import com.ruoyi.system.mapper.SysConfigMapper;
+import com.ruoyi.system.service.ISysConfigService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鍙傛暟閰嶇疆 鏈嶅姟灞傚疄鐜�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
+
+    private final SysConfigMapper baseMapper;
+
+    @Override
+    public TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery) {
+        Map<String, Object> params = config.getParams();
+        LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
+            .like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
+            .eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
+            .like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
+        Page<SysConfig> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     *
+     * @param configId 鍙傛暟閰嶇疆ID
+     * @return 鍙傛暟閰嶇疆淇℃伅
+     */
+    @Override
+    @DS("master")
+    public SysConfig selectConfigById(Long configId) {
+        return baseMapper.selectById(configId);
+    }
+
+    /**
+     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+     *
+     * @param configKey 鍙傛暟key
+     * @return 鍙傛暟閿��
+     */
+    @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey")
+    @Override
+    public String selectConfigByKey(String configKey) {
+        SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
+            .eq(SysConfig::getConfigKey, configKey));
+        if (ObjectUtil.isNotNull(retConfig)) {
+            return retConfig.getConfigValue();
+        }
+        return StringUtils.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇楠岃瘉鐮佸紑鍏�
+     *
+     * @return true寮�鍚紝false鍏抽棴
+     */
+    @Override
+    public boolean selectCaptchaEnabled() {
+        String captchaEnabled = SpringUtils.getAopProxy(this).selectConfigByKey("sys.account.captchaEnabled");
+        if (StringUtils.isEmpty(captchaEnabled)) {
+            return true;
+        }
+        return Convert.toBool(captchaEnabled);
+    }
+
+    /**
+     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 鍙傛暟閰嶇疆闆嗗悎
+     */
+    @Override
+    public List<SysConfig> selectConfigList(SysConfig config) {
+        Map<String, Object> params = config.getParams();
+        LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
+            .like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
+            .eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
+            .like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
+        return baseMapper.selectList(lqw);
+    }
+
+    /**
+     * 鏂板鍙傛暟閰嶇疆
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey")
+    @Override
+    public String insertConfig(SysConfig config) {
+        int row = baseMapper.insert(config);
+        if (row > 0) {
+            return config.getConfigValue();
+        }
+        throw new ServiceException("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 淇敼鍙傛暟閰嶇疆
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey")
+    @Override
+    public String updateConfig(SysConfig config) {
+        int row = 0;
+        if (config.getConfigId() != null) {
+            SysConfig temp = baseMapper.selectById(config.getConfigId());
+            if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
+                CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey());
+            }
+            row = baseMapper.updateById(config);
+        } else {
+            row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
+                .eq(SysConfig::getConfigKey, config.getConfigKey()));
+        }
+        if (row > 0) {
+            return config.getConfigValue();
+        }
+        throw new ServiceException("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+     *
+     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+     */
+    @Override
+    public void deleteConfigByIds(Long[] configIds) {
+        for (Long configId : configIds) {
+            SysConfig config = selectConfigById(configId);
+            if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
+                throw new ServiceException(String.format("鍐呯疆鍙傛暟銆�%1$s銆戜笉鑳藉垹闄� ", config.getConfigKey()));
+            }
+            CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
+        }
+        baseMapper.deleteBatchIds(Arrays.asList(configIds));
+    }
+
+    /**
+     * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
+     */
+    @Override
+    public void loadingConfigCache() {
+        List<SysConfig> configsList = selectConfigList(new SysConfig());
+        configsList.forEach(config ->
+            CacheUtils.put(CacheNames.SYS_CONFIG, config.getConfigKey(), config.getConfigValue()));
+    }
+
+    /**
+     * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
+     */
+    @Override
+    public void clearConfigCache() {
+        CacheUtils.clear(CacheNames.SYS_CONFIG);
+    }
+
+    /**
+     * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
+     */
+    @Override
+    public void resetConfigCache() {
+        clearConfigCache();
+        loadingConfigCache();
+    }
+
+    /**
+     * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
+     *
+     * @param config 鍙傛暟閰嶇疆淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkConfigKeyUnique(SysConfig config) {
+        Long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId();
+        SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey()));
+        if (ObjectUtil.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍规嵁鍙傛暟 key 鑾峰彇鍙傛暟鍊�
+     *
+     * @param configKey 鍙傛暟 key
+     * @return 鍙傛暟鍊�
+     */
+    @Override
+    public String getConfigValue(String configKey) {
+        return SpringUtils.getAopProxy(this).selectConfigByKey(configKey);
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java
new file mode 100644
index 0000000..7a75ae3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java
@@ -0,0 +1,61 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.system.domain.SysDept;
+import com.ruoyi.common.mybatis.helper.DataBaseHelper;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.system.domain.SysRoleDept;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.system.mapper.SysRoleDeptMapper;
+import com.ruoyi.system.service.ISysDataScopeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 鏁版嵁鏉冮檺 瀹炵幇
+ * <p>
+ * 娉ㄦ剰: 姝ervice鍐呬笉鍏佽璋冪敤鏍囨敞`鏁版嵁鏉冮檺`娉ㄨВ鐨勬柟娉�
+ * 渚嬪: deptMapper.selectList 姝� selectList 鏂规硶鏍囨敞浜哷鏁版嵁鏉冮檺`娉ㄨВ 浼氬嚭鐜板惊鐜В鏋愮殑闂
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service("sdss")
+public class SysDataScopeServiceImpl implements ISysDataScopeService {
+
+    private final SysRoleDeptMapper roleDeptMapper;
+    private final SysDeptMapper deptMapper;
+
+    @Override
+    public String getRoleCustom(Long roleId) {
+        List<SysRoleDept> list = roleDeptMapper.selectList(
+            new LambdaQueryWrapper<SysRoleDept>()
+                .select(SysRoleDept::getDeptId)
+                .eq(SysRoleDept::getRoleId, roleId));
+        if (CollUtil.isNotEmpty(list)) {
+            return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId()));
+        }
+        return null;
+    }
+
+    @Override
+    public String getDeptAndChild(Long deptId) {
+        List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
+            .select(SysDept::getDeptId)
+            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
+        List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
+        ids.add(deptId);
+        List<SysDept> list = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
+            .select(SysDept::getDeptId)
+            .in(SysDept::getDeptId, ids));
+        if (CollUtil.isNotEmpty(list)) {
+            return StreamUtils.join(list, d -> Convert.toStr(d.getDeptId()));
+        }
+        return null;
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
new file mode 100644
index 0000000..85c30d3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
@@ -0,0 +1,278 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.system.domain.SysDept;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.mybatis.helper.DataBaseHelper;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.TreeBuildUtils;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.service.ISysDeptService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 閮ㄩ棬绠$悊 鏈嶅姟瀹炵幇
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysDeptServiceImpl implements ISysDeptService {
+
+    private final SysDeptMapper baseMapper;
+    private final SysRoleMapper roleMapper;
+    private final SysUserMapper userMapper;
+
+    /**
+     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+     *
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬淇℃伅闆嗗悎
+     */
+    @Override
+    public List<SysDept> selectDeptList(SysDept dept) {
+        LambdaQueryWrapper<SysDept> lqw = new LambdaQueryWrapper<>();
+        lqw.eq(SysDept::getDelFlag, "0")
+            .eq(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())
+            .eq(ObjectUtil.isNotNull(dept.getParentId()), SysDept::getParentId, dept.getParentId())
+            .like(StringUtils.isNotBlank(dept.getDeptName()), SysDept::getDeptName, dept.getDeptName())
+            .eq(StringUtils.isNotBlank(dept.getStatus()), SysDept::getStatus, dept.getStatus())
+            .orderByAsc(SysDept::getParentId)
+            .orderByAsc(SysDept::getOrderNum);
+        return baseMapper.selectDeptList(lqw);
+    }
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
+     *
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
+     */
+    @Override
+    public List<Tree<Long>> selectDeptTreeList(SysDept dept) {
+        List<SysDept> depts = this.selectDeptList(dept);
+        return buildDeptTreeSelect(depts);
+    }
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+     *
+     * @param depts 閮ㄩ棬鍒楄〃
+     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+     */
+    @Override
+    public List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts) {
+        if (CollUtil.isEmpty(depts)) {
+            return CollUtil.newArrayList();
+        }
+        return TreeBuildUtils.build(depts, (dept, tree) ->
+            tree.setId(dept.getDeptId())
+                .setParentId(dept.getParentId())
+                .setName(dept.getDeptName())
+                .setWeight(dept.getOrderNum()));
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 閫変腑閮ㄩ棬鍒楄〃
+     */
+    @Override
+    public List<Long> selectDeptListByRoleId(Long roleId) {
+        SysRole role = roleMapper.selectById(roleId);
+        return baseMapper.selectDeptListByRoleId(roleId, role.getDeptCheckStrictly());
+    }
+
+    /**
+     * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+     *
+     * @param deptId 閮ㄩ棬ID
+     * @return 閮ㄩ棬淇℃伅
+     */
+    @Override
+    public SysDept selectDeptById(Long deptId) {
+        SysDept dept = baseMapper.selectById(deptId);
+        SysDept parentDept = baseMapper.selectOne(new LambdaQueryWrapper<SysDept>()
+            .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId()));
+        dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null);
+        return dept;
+    }
+
+    /**
+     * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬鏁帮紙姝e父鐘舵�侊級
+     *
+     * @param deptId 閮ㄩ棬ID
+     * @return 瀛愰儴闂ㄦ暟
+     */
+    @Override
+    public long selectNormalChildrenDeptById(Long deptId) {
+        return baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
+            .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
+            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
+    }
+
+    /**
+     * 鏄惁瀛樺湪瀛愯妭鐐�
+     *
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean hasChildByDeptId(Long deptId) {
+        return baseMapper.exists(new LambdaQueryWrapper<SysDept>()
+            .eq(SysDept::getParentId, deptId));
+    }
+
+    /**
+     * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+     *
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+     */
+    @Override
+    public boolean checkDeptExistUser(Long deptId) {
+        return userMapper.exists(new LambdaQueryWrapper<SysUser>()
+            .eq(SysUser::getDeptId, deptId));
+    }
+
+    /**
+     * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+     *
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkDeptNameUnique(SysDept dept) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDept>()
+            .eq(SysDept::getDeptName, dept.getDeptName())
+            .eq(SysDept::getParentId, dept.getParentId())
+            .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙閮ㄩ棬鏄惁鏈夋暟鎹潈闄�
+     *
+     * @param deptId 閮ㄩ棬id
+     */
+    @Override
+    public void checkDeptDataScope(Long deptId) {
+        if (!LoginHelper.isAdmin()) {
+            SysDept dept = new SysDept();
+            dept.setDeptId(deptId);
+            List<SysDept> depts = this.selectDeptList(dept);
+            if (CollUtil.isEmpty(depts)) {
+                throw new ServiceException("娌℃湁鏉冮檺璁块棶閮ㄩ棬鏁版嵁锛�");
+            }
+        }
+    }
+
+    /**
+     * 鏂板淇濆瓨閮ㄩ棬淇℃伅
+     *
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertDept(SysDept dept) {
+        SysDept info = baseMapper.selectById(dept.getParentId());
+        // 濡傛灉鐖惰妭鐐逛笉涓烘甯哥姸鎬�,鍒欎笉鍏佽鏂板瀛愯妭鐐�
+        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
+            throw new ServiceException("閮ㄩ棬鍋滅敤锛屼笉鍏佽鏂板");
+        }
+        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
+        return baseMapper.insert(dept);
+    }
+
+    /**
+     * 淇敼淇濆瓨閮ㄩ棬淇℃伅
+     *
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateDept(SysDept dept) {
+        SysDept newParentDept = baseMapper.selectById(dept.getParentId());
+        SysDept oldDept = baseMapper.selectById(dept.getDeptId());
+        if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) {
+            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
+            String oldAncestors = oldDept.getAncestors();
+            dept.setAncestors(newAncestors);
+            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
+        }
+        int result = baseMapper.updateById(dept);
+        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
+            && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) {
+            // 濡傛灉璇ラ儴闂ㄦ槸鍚敤鐘舵�侊紝鍒欏惎鐢ㄨ閮ㄩ棬鐨勬墍鏈変笂绾ч儴闂�
+            updateParentDeptStatusNormal(dept);
+        }
+        return result;
+    }
+
+    /**
+     * 淇敼璇ラ儴闂ㄧ殑鐖剁骇閮ㄩ棬鐘舵��
+     *
+     * @param dept 褰撳墠閮ㄩ棬
+     */
+    private void updateParentDeptStatusNormal(SysDept dept) {
+        String ancestors = dept.getAncestors();
+        Long[] deptIds = Convert.toLongArray(ancestors);
+        baseMapper.update(null, new LambdaUpdateWrapper<SysDept>()
+            .set(SysDept::getStatus, UserConstants.DEPT_NORMAL)
+            .in(SysDept::getDeptId, Arrays.asList(deptIds)));
+    }
+
+    /**
+     * 淇敼瀛愬厓绱犲叧绯�
+     *
+     * @param deptId       琚慨鏀圭殑閮ㄩ棬ID
+     * @param newAncestors 鏂扮殑鐖禝D闆嗗悎
+     * @param oldAncestors 鏃х殑鐖禝D闆嗗悎
+     */
+    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
+        List<SysDept> children = baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
+            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
+        List<SysDept> list = new ArrayList<>();
+        for (SysDept child : children) {
+            SysDept dept = new SysDept();
+            dept.setDeptId(child.getDeptId());
+            dept.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
+            list.add(dept);
+        }
+        if (list.size() > 0) {
+            baseMapper.updateBatchById(list);
+        }
+    }
+
+    /**
+     * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+     *
+     * @param deptId 閮ㄩ棬ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteDeptById(Long deptId) {
+        return baseMapper.deleteById(deptId);
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
new file mode 100644
index 0000000..5d06194
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
@@ -0,0 +1,130 @@
+package com.ruoyi.system.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.system.domain.SysDictData;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.system.mapper.SysDictDataMapper;
+import com.ruoyi.system.service.ISysDictDataService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 瀛楀吀 涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysDictDataServiceImpl implements ISysDictDataService {
+
+    private final SysDictDataMapper baseMapper;
+
+    @Override
+    public TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysDictData> lqw = new LambdaQueryWrapper<SysDictData>()
+            .eq(StringUtils.isNotBlank(dictData.getDictType()), SysDictData::getDictType, dictData.getDictType())
+            .like(StringUtils.isNotBlank(dictData.getDictLabel()), SysDictData::getDictLabel, dictData.getDictLabel())
+            .eq(StringUtils.isNotBlank(dictData.getStatus()), SysDictData::getStatus, dictData.getStatus())
+            .orderByAsc(SysDictData::getDictSort);
+        Page<SysDictData> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+     *
+     * @param dictData 瀛楀吀鏁版嵁淇℃伅
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictData> selectDictDataList(SysDictData dictData) {
+        return baseMapper.selectList(new LambdaQueryWrapper<SysDictData>()
+            .eq(StringUtils.isNotBlank(dictData.getDictType()), SysDictData::getDictType, dictData.getDictType())
+            .like(StringUtils.isNotBlank(dictData.getDictLabel()), SysDictData::getDictLabel, dictData.getDictLabel())
+            .eq(StringUtils.isNotBlank(dictData.getStatus()), SysDictData::getStatus, dictData.getStatus())
+            .orderByAsc(SysDictData::getDictSort));
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+     *
+     * @param dictType  瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀閿��
+     * @return 瀛楀吀鏍囩
+     */
+    @Override
+    public String selectDictLabel(String dictType, String dictValue) {
+        return baseMapper.selectOne(new LambdaQueryWrapper<SysDictData>()
+                .select(SysDictData::getDictLabel)
+                .eq(SysDictData::getDictType, dictType)
+                .eq(SysDictData::getDictValue, dictValue))
+            .getDictLabel();
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+     *
+     * @param dictCode 瀛楀吀鏁版嵁ID
+     * @return 瀛楀吀鏁版嵁
+     */
+    @Override
+    public SysDictData selectDictDataById(Long dictCode) {
+        return baseMapper.selectById(dictCode);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+     */
+    @Override
+    public void deleteDictDataByIds(Long[] dictCodes) {
+        for (Long dictCode : dictCodes) {
+            SysDictData data = selectDictDataById(dictCode);
+            baseMapper.deleteById(dictCode);
+            CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType());
+        }
+    }
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param data 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType")
+    @Override
+    public List<SysDictData> insertDictData(SysDictData data) {
+        int row = baseMapper.insert(data);
+        if (row > 0) {
+            return baseMapper.selectDictDataByType(data.getDictType());
+        }
+        throw new ServiceException("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
+     *
+     * @param data 瀛楀吀鏁版嵁淇℃伅
+     * @return 缁撴灉
+     */
+    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType")
+    @Override
+    public List<SysDictData> updateDictData(SysDictData data) {
+        int row = baseMapper.updateById(data);
+        if (row > 0) {
+            return baseMapper.selectDictDataByType(data.getDictType());
+        }
+        throw new ServiceException("鎿嶄綔澶辫触");
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
new file mode 100644
index 0000000..dd155ae
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -0,0 +1,285 @@
+package com.ruoyi.system.service.impl;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.core.service.DictService;
+import com.ruoyi.system.domain.SysDictData;
+import com.ruoyi.system.domain.SysDictType;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.system.mapper.SysDictDataMapper;
+import com.ruoyi.system.mapper.SysDictTypeMapper;
+import com.ruoyi.system.service.ISysDictTypeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 瀛楀吀 涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService {
+
+    private final SysDictTypeMapper baseMapper;
+    private final SysDictDataMapper dictDataMapper;
+
+    @Override
+    public TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery) {
+        Map<String, Object> params = dictType.getParams();
+        LambdaQueryWrapper<SysDictType> lqw = new LambdaQueryWrapper<SysDictType>()
+            .like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
+            .eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
+            .like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime"));
+        Page<SysDictType> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+     *
+     * @param dictType 瀛楀吀绫诲瀷淇℃伅
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictType> selectDictTypeList(SysDictType dictType) {
+        Map<String, Object> params = dictType.getParams();
+        return baseMapper.selectList(new LambdaQueryWrapper<SysDictType>()
+            .like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
+            .eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
+            .like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime")));
+    }
+
+    /**
+     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+     *
+     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysDictType> selectDictTypeAll() {
+        return baseMapper.selectList();
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+     */
+    @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
+    @Override
+    public List<SysDictData> selectDictDataByType(String dictType) {
+        List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType);
+        if (CollUtil.isNotEmpty(dictDatas)) {
+            return dictDatas;
+        }
+        return null;
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+     *
+     * @param dictId 瀛楀吀绫诲瀷ID
+     * @return 瀛楀吀绫诲瀷
+     */
+    @Override
+    public SysDictType selectDictTypeById(Long dictId) {
+        return baseMapper.selectById(dictId);
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+     *
+     * @param dictType 瀛楀吀绫诲瀷
+     * @return 瀛楀吀绫诲瀷
+     */
+    @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
+    @Override
+    public SysDictType selectDictTypeByType(String dictType) {
+        return baseMapper.selectById(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getDictType, dictType));
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
+     *
+     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+     */
+    @Override
+    public void deleteDictTypeByIds(Long[] dictIds) {
+        for (Long dictId : dictIds) {
+            SysDictType dictType = selectDictTypeById(dictId);
+            if (dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
+                .eq(SysDictData::getDictType, dictType.getDictType()))) {
+                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", dictType.getDictName()));
+            }
+            CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType());
+        }
+        baseMapper.deleteBatchIds(Arrays.asList(dictIds));
+    }
+
+    /**
+     * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
+     */
+    @Override
+    public void loadingDictCache() {
+        List<SysDictData> dictDataList = dictDataMapper.selectList(
+            new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getStatus, UserConstants.DICT_NORMAL));
+        Map<String, List<SysDictData>> dictDataMap = StreamUtils.groupByKey(dictDataList, SysDictData::getDictType);
+        dictDataMap.forEach((k,v) -> {
+            List<SysDictData> dictList = StreamUtils.sorted(v, Comparator.comparing(SysDictData::getDictSort));
+            CacheUtils.put(CacheNames.SYS_DICT, k, dictList);
+        });
+    }
+
+    /**
+     * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
+     */
+    @Override
+    public void clearDictCache() {
+        CacheUtils.clear(CacheNames.SYS_DICT);
+    }
+
+    /**
+     * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
+     */
+    @Override
+    public void resetDictCache() {
+        clearDictCache();
+        loadingDictCache();
+    }
+
+    /**
+     * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     *
+     * @param dict 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType")
+    @Override
+    public List<SysDictData> insertDictType(SysDictType dict) {
+        int row = baseMapper.insert(dict);
+        if (row > 0) {
+            return new ArrayList<>();
+        }
+        throw new ServiceException("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
+     *
+     * @param dict 瀛楀吀绫诲瀷淇℃伅
+     * @return 缁撴灉
+     */
+    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType")
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public List<SysDictData> updateDictType(SysDictType dict) {
+        SysDictType oldDict = baseMapper.selectById(dict.getDictId());
+        dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>()
+            .set(SysDictData::getDictType, dict.getDictType())
+            .eq(SysDictData::getDictType, oldDict.getDictType()));
+        int row = baseMapper.updateById(dict);
+        if (row > 0) {
+            CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType());
+            return dictDataMapper.selectDictDataByType(dict.getDictType());
+        }
+        throw new ServiceException("鎿嶄綔澶辫触");
+    }
+
+    /**
+     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+     *
+     * @param dict 瀛楀吀绫诲瀷
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkDictTypeUnique(SysDictType dict) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDictType>()
+            .eq(SysDictType::getDictType, dict.getDictType())
+            .ne(ObjectUtil.isNotNull(dict.getDictId()), SysDictType::getDictId, dict.getDictId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+     *
+     * @param dictType  瀛楀吀绫诲瀷
+     * @param dictValue 瀛楀吀鍊�
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鏍囩
+     */
+    @SuppressWarnings("unchecked cast")
+    @Override
+    public String getDictLabel(String dictType, String dictValue, String separator) {
+        // 浼樺厛浠庢湰鍦扮紦瀛樿幏鍙�
+        List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
+        if (ObjectUtil.isNull(datas)) {
+            datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
+            SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
+        }
+
+        Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictValue, SysDictData::getDictLabel);
+        if (StringUtils.containsAny(dictValue, separator)) {
+            return Arrays.stream(dictValue.split(separator))
+                .map(v -> map.getOrDefault(v, StringUtils.EMPTY))
+                .collect(Collectors.joining(separator));
+        } else {
+            return map.getOrDefault(dictValue, StringUtils.EMPTY);
+        }
+    }
+
+    /**
+     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+     *
+     * @param dictType  瀛楀吀绫诲瀷
+     * @param dictLabel 瀛楀吀鏍囩
+     * @param separator 鍒嗛殧绗�
+     * @return 瀛楀吀鍊�
+     */
+    @SuppressWarnings("unchecked cast")
+    @Override
+    public String getDictValue(String dictType, String dictLabel, String separator) {
+        // 浼樺厛浠庢湰鍦扮紦瀛樿幏鍙�
+        List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
+        if (ObjectUtil.isNull(datas)) {
+            datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
+            SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
+        }
+
+        Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictLabel, SysDictData::getDictValue);
+        if (StringUtils.containsAny(dictLabel, separator)) {
+            return Arrays.stream(dictLabel.split(separator))
+                .map(l -> map.getOrDefault(l, StringUtils.EMPTY))
+                .collect(Collectors.joining(separator));
+        } else {
+            return map.getOrDefault(dictLabel, StringUtils.EMPTY);
+        }
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
new file mode 100644
index 0000000..492dd1c
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
@@ -0,0 +1,155 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.http.useragent.UserAgent;
+import cn.hutool.http.useragent.UserAgentUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.log.event.LogininforEvent;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.ip.AddressUtils;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.mapper.SysLogininforMapper;
+import com.ruoyi.system.service.ISysLogininforService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Slf4j
+@Service
+public class SysLogininforServiceImpl implements ISysLogininforService {
+
+    private final SysLogininforMapper baseMapper;
+
+    /**
+     * 璁板綍鐧诲綍淇℃伅
+     *
+     * @param logininforEvent 鐧诲綍浜嬩欢
+     */
+    @Async
+    @EventListener
+    public void recordLogininfor(LogininforEvent logininforEvent) {
+        HttpServletRequest request = logininforEvent.getRequest();
+        final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
+        final String ip = ServletUtils.getClientIP(request);
+
+        String address = AddressUtils.getRealAddressByIP(ip);
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(ip));
+        s.append(address);
+        s.append(getBlock(logininforEvent.getUsername()));
+        s.append(getBlock(logininforEvent.getStatus()));
+        s.append(getBlock(logininforEvent.getMessage()));
+        // 鎵撳嵃淇℃伅鍒版棩蹇�
+        log.info(s.toString(), logininforEvent.getArgs());
+        // 鑾峰彇瀹㈡埛绔搷浣滅郴缁�
+        String os = userAgent.getOs().getName();
+        // 鑾峰彇瀹㈡埛绔祻瑙堝櫒
+        String browser = userAgent.getBrowser().getName();
+        // 灏佽瀵硅薄
+        SysLogininfor logininfor = new SysLogininfor();
+        logininfor.setUserName(logininforEvent.getUsername());
+        logininfor.setIpaddr(ip);
+        logininfor.setLoginLocation(address);
+        logininfor.setBrowser(browser);
+        logininfor.setOs(os);
+        logininfor.setMsg(logininforEvent.getMessage());
+        // 鏃ュ織鐘舵��
+        if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
+            logininfor.setStatus(Constants.SUCCESS);
+        } else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) {
+            logininfor.setStatus(Constants.FAIL);
+        }
+        // 鎻掑叆鏁版嵁
+        insertLogininfor(logininfor);
+    }
+
+    private String getBlock(Object msg) {
+        if (msg == null) {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+
+    @Override
+    public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery) {
+        Map<String, Object> params = logininfor.getParams();
+        LambdaQueryWrapper<SysLogininfor> lqw = new LambdaQueryWrapper<SysLogininfor>()
+            .like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
+            .eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
+            .like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"));
+        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
+            pageQuery.setOrderByColumn("info_id");
+            pageQuery.setIsAsc("desc");
+        }
+        Page<SysLogininfor> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏂板绯荤粺鐧诲綍鏃ュ織
+     *
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     */
+    @Override
+    public void insertLogininfor(SysLogininfor logininfor) {
+        logininfor.setLoginTime(new Date());
+        baseMapper.insert(logininfor);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+     *
+     * @param logininfor 璁块棶鏃ュ織瀵硅薄
+     * @return 鐧诲綍璁板綍闆嗗悎
+     */
+    @Override
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor) {
+        Map<String, Object> params = logininfor.getParams();
+        return baseMapper.selectList(new LambdaQueryWrapper<SysLogininfor>()
+            .like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
+            .eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
+            .like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"))
+            .orderByDesc(SysLogininfor::getInfoId));
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+     *
+     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteLogininforByIds(Long[] infoIds) {
+        return baseMapper.deleteBatchIds(Arrays.asList(infoIds));
+    }
+
+    /**
+     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+     */
+    @Override
+    public void cleanLogininfor() {
+        baseMapper.delete(new LambdaQueryWrapper<>());
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
new file mode 100644
index 0000000..03337b7
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
@@ -0,0 +1,446 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.system.domain.SysMenu;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.TreeBuildUtils;
+import com.ruoyi.system.domain.SysRoleMenu;
+import com.ruoyi.system.domain.vo.MetaVo;
+import com.ruoyi.system.domain.vo.RouterVo;
+import com.ruoyi.system.mapper.SysMenuMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysRoleMenuMapper;
+import com.ruoyi.system.service.ISysMenuService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * 鑿滃崟 涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysMenuServiceImpl implements ISysMenuService {
+
+    private final SysMenuMapper baseMapper;
+    private final SysRoleMapper roleMapper;
+    private final SysRoleMenuMapper roleMenuMapper;
+
+    /**
+     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<SysMenu> selectMenuList(Long userId) {
+        return selectMenuList(new SysMenu(), userId);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺鑿滃崟鍒楄〃
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<SysMenu> selectMenuList(SysMenu menu, Long userId) {
+        List<SysMenu> menuList = null;
+        // 绠$悊鍛樻樉绀烘墍鏈夎彍鍗曚俊鎭�
+        if (LoginHelper.isAdmin(userId)) {
+            menuList = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>()
+                .like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName())
+                .eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible())
+                .eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus())
+                .orderByAsc(SysMenu::getParentId)
+                .orderByAsc(SysMenu::getOrderNum));
+        } else {
+            QueryWrapper<SysMenu> wrapper = Wrappers.query();
+            wrapper.eq("sur.user_id", userId)
+                .like(StringUtils.isNotBlank(menu.getMenuName()), "m.menu_name", menu.getMenuName())
+                .eq(StringUtils.isNotBlank(menu.getVisible()), "m.visible", menu.getVisible())
+                .eq(StringUtils.isNotBlank(menu.getStatus()), "m.status", menu.getStatus())
+                .orderByAsc("m.parent_id")
+                .orderByAsc("m.order_num");
+            menuList = baseMapper.selectMenuListByUserId(wrapper);
+        }
+        return menuList;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    @Override
+    public Set<String> selectMenuPermsByUserId(Long userId) {
+        List<String> perms = baseMapper.selectMenuPermsByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    @Override
+    public Set<String> selectMenuPermsByRoleId(Long roleId) {
+        List<String> perms = baseMapper.selectMenuPermsByRoleId(roleId);
+        Set<String> permsSet = new HashSet<>();
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
+                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+     *
+     * @param userId 鐢ㄦ埛鍚嶇О
+     * @return 鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<SysMenu> selectMenuTreeByUserId(Long userId) {
+        List<SysMenu> menus = null;
+        if (LoginHelper.isAdmin(userId)) {
+            menus = baseMapper.selectMenuTreeAll();
+        } else {
+            menus = baseMapper.selectMenuTreeByUserId(userId);
+        }
+        return getChildPerms(menus, 0);
+    }
+
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 閫変腑鑿滃崟鍒楄〃
+     */
+    @Override
+    public List<Long> selectMenuListByRoleId(Long roleId) {
+        SysRole role = roleMapper.selectById(roleId);
+        return baseMapper.selectMenuListByRoleId(roleId, role.getMenuCheckStrictly());
+    }
+
+    /**
+     * 鏋勫缓鍓嶇璺敱鎵�闇�瑕佺殑鑿滃崟
+     *
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 璺敱鍒楄〃
+     */
+    @Override
+    public List<RouterVo> buildMenus(List<SysMenu> menus) {
+        List<RouterVo> routers = new LinkedList<RouterVo>();
+        for (SysMenu menu : menus) {
+            RouterVo router = new RouterVo();
+            router.setHidden("1".equals(menu.getVisible()));
+            router.setName(getRouteName(menu));
+            router.setPath(getRouterPath(menu));
+            router.setComponent(getComponent(menu));
+            router.setQuery(menu.getQueryParam());
+            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+            List<SysMenu> cMenus = menu.getChildren();
+            if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
+                router.setAlwaysShow(true);
+                router.setRedirect("noRedirect");
+                router.setChildren(buildMenus(cMenus));
+            } else if (isMenuFrame(menu)) {
+                router.setMeta(null);
+                List<RouterVo> childrenList = new ArrayList<RouterVo>();
+                RouterVo children = new RouterVo();
+                children.setPath(menu.getPath());
+                children.setComponent(menu.getComponent());
+                children.setName(StringUtils.capitalize(menu.getPath()));
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+                children.setQuery(menu.getQueryParam());
+                childrenList.add(children);
+                router.setChildren(childrenList);
+            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
+                router.setPath("/");
+                List<RouterVo> childrenList = new ArrayList<RouterVo>();
+                RouterVo children = new RouterVo();
+                String routerPath = innerLinkReplaceEach(menu.getPath());
+                children.setPath(routerPath);
+                children.setComponent(UserConstants.INNER_LINK);
+                children.setName(StringUtils.capitalize(routerPath));
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
+                childrenList.add(children);
+                router.setChildren(childrenList);
+            }
+            routers.add(router);
+        }
+        return routers;
+    }
+
+    /**
+     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+     *
+     * @param menus 鑿滃崟鍒楄〃
+     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+     */
+    @Override
+    public List<Tree<Long>> buildMenuTreeSelect(List<SysMenu> menus) {
+        if (CollUtil.isEmpty(menus)) {
+            return CollUtil.newArrayList();
+        }
+        return TreeBuildUtils.build(menus, (menu, tree) ->
+            tree.setId(menu.getMenuId())
+                .setParentId(menu.getParentId())
+                .setName(menu.getMenuName())
+                .setWeight(menu.getOrderNum()));
+    }
+
+    /**
+     * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 鑿滃崟淇℃伅
+     */
+    @Override
+    public SysMenu selectMenuById(Long menuId) {
+        return baseMapper.selectById(menuId);
+    }
+
+    /**
+     * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean hasChildByMenuId(Long menuId) {
+        return baseMapper.exists(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, menuId));
+    }
+
+    /**
+     * 鏌ヨ鑿滃崟浣跨敤鏁伴噺
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean checkMenuExistRole(Long menuId) {
+        return roleMenuMapper.exists(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getMenuId, menuId));
+    }
+
+    /**
+     * 鏂板淇濆瓨鑿滃崟淇℃伅
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertMenu(SysMenu menu) {
+        return baseMapper.insert(menu);
+    }
+
+    /**
+     * 淇敼淇濆瓨鑿滃崟淇℃伅
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateMenu(SysMenu menu) {
+        return baseMapper.updateById(menu);
+    }
+
+    /**
+     * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+     *
+     * @param menuId 鑿滃崟ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteMenuById(Long menuId) {
+        return baseMapper.deleteById(menuId);
+    }
+
+    /**
+     * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkMenuNameUnique(SysMenu menu) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysMenu>()
+            .eq(SysMenu::getMenuName, menu.getMenuName())
+            .eq(SysMenu::getParentId, menu.getParentId())
+            .ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鑾峰彇璺敱鍚嶇О
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 璺敱鍚嶇О
+     */
+    public String getRouteName(SysMenu menu) {
+        String routerName = StringUtils.capitalize(menu.getPath());
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+        if (isMenuFrame(menu)) {
+            routerName = StringUtils.EMPTY;
+        }
+        return routerName;
+    }
+
+    /**
+     * 鑾峰彇璺敱鍦板潃
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 璺敱鍦板潃
+     */
+    public String getRouterPath(SysMenu menu) {
+        String routerPath = menu.getPath();
+        // 鍐呴摼鎵撳紑澶栫綉鏂瑰紡
+        if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
+            routerPath = innerLinkReplaceEach(routerPath);
+        }
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+        if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
+            && UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
+            routerPath = "/" + menu.getPath();
+        }
+        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓鸿彍鍗曪級
+        else if (isMenuFrame(menu)) {
+            routerPath = "/";
+        }
+        return routerPath;
+    }
+
+    /**
+     * 鑾峰彇缁勪欢淇℃伅
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁勪欢淇℃伅
+     */
+    public String getComponent(SysMenu menu) {
+        String component = UserConstants.LAYOUT;
+        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
+            component = menu.getComponent();
+        } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
+            component = UserConstants.INNER_LINK;
+        } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) {
+            component = UserConstants.PARENT_VIEW;
+        }
+        return component;
+    }
+
+    /**
+     * 鏄惁涓鸿彍鍗曞唴閮ㄨ烦杞�
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean isMenuFrame(SysMenu menu) {
+        return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
+            && menu.getIsFrame().equals(UserConstants.NO_FRAME);
+    }
+
+    /**
+     * 鏄惁涓哄唴閾剧粍浠�
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean isInnerLink(SysMenu menu) {
+        return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
+    }
+
+    /**
+     * 鏄惁涓簆arent_view缁勪欢
+     *
+     * @param menu 鑿滃崟淇℃伅
+     * @return 缁撴灉
+     */
+    public boolean isParentView(SysMenu menu) {
+        return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
+    }
+
+    /**
+     * 鏍规嵁鐖惰妭鐐圭殑ID鑾峰彇鎵�鏈夊瓙鑺傜偣
+     *
+     * @param list     鍒嗙被琛�
+     * @param parentId 浼犲叆鐨勭埗鑺傜偣ID
+     * @return String
+     */
+    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
+        List<SysMenu> returnList = new ArrayList<SysMenu>();
+        for (SysMenu t : list) {
+            // 涓�銆佹牴鎹紶鍏ョ殑鏌愪釜鐖惰妭鐐笽D,閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+            if (t.getParentId() == parentId) {
+                recursionFn(list, t);
+                returnList.add(t);
+            }
+        }
+        return returnList;
+    }
+
+    /**
+     * 閫掑綊鍒楄〃
+     *
+     * @param list
+     * @param t
+     */
+    private void recursionFn(List<SysMenu> list, SysMenu t) {
+        // 寰楀埌瀛愯妭鐐瑰垪琛�
+        List<SysMenu> childList = getChildList(list, t);
+        t.setChildren(childList);
+        for (SysMenu tChild : childList) {
+            if (hasChild(list, tChild)) {
+                recursionFn(list, tChild);
+            }
+        }
+    }
+
+    /**
+     * 寰楀埌瀛愯妭鐐瑰垪琛�
+     */
+    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
+        return StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId()));
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁鏈夊瓙鑺傜偣
+     */
+    private boolean hasChild(List<SysMenu> list, SysMenu t) {
+        return getChildList(list, t).size() > 0;
+    }
+
+    /**
+     * 鍐呴摼鍩熷悕鐗规畩瀛楃鏇挎崲
+     */
+    public String innerLinkReplaceEach(String path) {
+        return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, "."},
+            new String[]{"", "", "", "/"});
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
new file mode 100644
index 0000000..2cdacb7
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
@@ -0,0 +1,106 @@
+package com.ruoyi.system.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.system.domain.SysNotice;
+import com.ruoyi.system.mapper.SysNoticeMapper;
+import com.ruoyi.system.service.ISysNoticeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 鍏憡 鏈嶅姟灞傚疄鐜�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysNoticeServiceImpl implements ISysNoticeService {
+
+    private final SysNoticeMapper baseMapper;
+
+    @Override
+    public TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysNotice> lqw = new LambdaQueryWrapper<SysNotice>()
+            .like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())
+            .eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())
+            .like(StringUtils.isNotBlank(notice.getCreateBy()), SysNotice::getCreateBy, notice.getCreateBy());
+        Page<SysNotice> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏌ヨ鍏憡淇℃伅
+     *
+     * @param noticeId 鍏憡ID
+     * @return 鍏憡淇℃伅
+     */
+    @Override
+    public SysNotice selectNoticeById(Long noticeId) {
+        return baseMapper.selectById(noticeId);
+    }
+
+    /**
+     * 鏌ヨ鍏憡鍒楄〃
+     *
+     * @param notice 鍏憡淇℃伅
+     * @return 鍏憡闆嗗悎
+     */
+    @Override
+    public List<SysNotice> selectNoticeList(SysNotice notice) {
+        return baseMapper.selectList(new LambdaQueryWrapper<SysNotice>()
+            .like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())
+            .eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())
+            .like(StringUtils.isNotBlank(notice.getCreateBy()), SysNotice::getCreateBy, notice.getCreateBy()));
+    }
+
+    /**
+     * 鏂板鍏憡
+     *
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertNotice(SysNotice notice) {
+        return baseMapper.insert(notice);
+    }
+
+    /**
+     * 淇敼鍏憡
+     *
+     * @param notice 鍏憡淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateNotice(SysNotice notice) {
+        return baseMapper.updateById(notice);
+    }
+
+    /**
+     * 鍒犻櫎鍏憡瀵硅薄
+     *
+     * @param noticeId 鍏憡ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteNoticeById(Long noticeId) {
+        return baseMapper.deleteById(noticeId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鍏憡淇℃伅
+     *
+     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteNoticeByIds(Long[] noticeIds) {
+        return baseMapper.deleteBatchIds(Arrays.asList(noticeIds));
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
new file mode 100644
index 0000000..2d89d77
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
@@ -0,0 +1,141 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ArrayUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.ip.AddressUtils;
+import com.ruoyi.common.log.event.OperLogEvent;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.mapper.SysOperLogMapper;
+import com.ruoyi.system.service.ISysOperLogService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏈嶅姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysOperLogServiceImpl implements ISysOperLogService {
+
+    private final SysOperLogMapper baseMapper;
+
+    /**
+     * 鎿嶄綔鏃ュ織璁板綍
+     *
+     * @param operLogEvent 鎿嶄綔鏃ュ織浜嬩欢
+     */
+    @Async
+    @EventListener
+    public void recordOper(OperLogEvent operLogEvent) {
+        SysOperLog operLog = BeanUtil.toBean(operLogEvent, SysOperLog.class);
+        // 杩滅▼鏌ヨ鎿嶄綔鍦扮偣
+        operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
+        insertOperlog(operLog);
+    }
+
+    @Override
+    public TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog, PageQuery pageQuery) {
+        Map<String, Object> params = operLog.getParams();
+        LambdaQueryWrapper<SysOperLog> lqw = new LambdaQueryWrapper<SysOperLog>()
+            .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
+            .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
+                SysOperLog::getBusinessType, operLog.getBusinessType())
+            .func(f -> {
+                if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
+                    f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
+                }
+            })
+            .eq(operLog.getStatus() != null,
+                SysOperLog::getStatus, operLog.getStatus())
+            .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"));
+        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
+            pageQuery.setOrderByColumn("oper_id");
+            pageQuery.setIsAsc("desc");
+        }
+        Page<SysOperLog> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏂板鎿嶄綔鏃ュ織
+     *
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    @Override
+    public void insertOperlog(SysOperLog operLog) {
+        operLog.setOperTime(new Date());
+        baseMapper.insert(operLog);
+    }
+
+    /**
+     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+     *
+     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+     * @return 鎿嶄綔鏃ュ織闆嗗悎
+     */
+    @Override
+    public List<SysOperLog> selectOperLogList(SysOperLog operLog) {
+        Map<String, Object> params = operLog.getParams();
+        return baseMapper.selectList(new LambdaQueryWrapper<SysOperLog>()
+            .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
+            .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
+                SysOperLog::getBusinessType, operLog.getBusinessType())
+            .func(f -> {
+                if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
+                    f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
+                }
+            })
+            .eq(operLog.getStatus() != null && operLog.getStatus() > 0,
+                SysOperLog::getStatus, operLog.getStatus())
+            .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"))
+            .orderByDesc(SysOperLog::getOperId));
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+     *
+     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteOperLogByIds(Long[] operIds) {
+        return baseMapper.deleteBatchIds(Arrays.asList(operIds));
+    }
+
+    /**
+     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+     *
+     * @param operId 鎿嶄綔ID
+     * @return 鎿嶄綔鏃ュ織瀵硅薄
+     */
+    @Override
+    public SysOperLog selectOperLogById(Long operId) {
+        return baseMapper.selectById(operId);
+    }
+
+    /**
+     * 娓呯┖鎿嶄綔鏃ュ織
+     */
+    @Override
+    public void cleanOperLog() {
+        baseMapper.delete(new LambdaQueryWrapper<>());
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
new file mode 100644
index 0000000..8d20845
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
@@ -0,0 +1,189 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.constant.OssConstant;
+import com.ruoyi.common.oss.factory.OssFactory;
+import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.system.domain.SysOssConfig;
+import com.ruoyi.system.domain.bo.SysOssConfigBo;
+import com.ruoyi.system.domain.vo.SysOssConfigVo;
+import com.ruoyi.system.mapper.SysOssConfigMapper;
+import com.ruoyi.system.service.ISysOssConfigService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 瀵硅薄瀛樺偍閰嶇疆Service涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ * @author 瀛よ垷鐑熼洦
+ * @date 2021-08-13
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class SysOssConfigServiceImpl implements ISysOssConfigService {
+
+    private final SysOssConfigMapper baseMapper;
+
+    /**
+     * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧弬鏁板埌缂撳瓨锛屽姞杞介厤缃被
+     */
+    @Override
+    public void init() {
+        List<SysOssConfig> list = baseMapper.selectList();
+        // 鍔犺浇OSS鍒濆鍖栭厤缃�
+        for (SysOssConfig config : list) {
+            String configKey = config.getConfigKey();
+            if ("0".equals(config.getStatus())) {
+                RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
+            }
+            SpringUtils.context().publishEvent(config);
+        }
+        // 鍒濆鍖朞SS宸ュ巶
+        OssFactory.init();
+    }
+
+    @Override
+    public SysOssConfigVo queryById(Long ossConfigId) {
+        return baseMapper.selectVoById(ossConfigId);
+    }
+
+    @Override
+    public TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysOssConfig> lqw = buildQueryWrapper(bo);
+        Page<SysOssConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+
+    private LambdaQueryWrapper<SysOssConfig> buildQueryWrapper(SysOssConfigBo bo) {
+        LambdaQueryWrapper<SysOssConfig> lqw = Wrappers.lambdaQuery();
+        lqw.eq(StringUtils.isNotBlank(bo.getConfigKey()), SysOssConfig::getConfigKey, bo.getConfigKey());
+        lqw.like(StringUtils.isNotBlank(bo.getBucketName()), SysOssConfig::getBucketName, bo.getBucketName());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysOssConfig::getStatus, bo.getStatus());
+        return lqw;
+    }
+
+    @Override
+    public Boolean insertByBo(SysOssConfigBo bo) {
+        SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
+        validEntityBeforeSave(config);
+        boolean flag = baseMapper.insert(config) > 0;
+        if (flag) {
+            SpringUtils.context().publishEvent(config);
+        }
+        return flag;
+    }
+
+    @Override
+    public Boolean updateByBo(SysOssConfigBo bo) {
+        SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
+        validEntityBeforeSave(config);
+        LambdaUpdateWrapper<SysOssConfig> luw = new LambdaUpdateWrapper<>();
+        luw.set(ObjectUtil.isNull(config.getPrefix()), SysOssConfig::getPrefix, "");
+        luw.set(ObjectUtil.isNull(config.getRegion()), SysOssConfig::getRegion, "");
+        luw.set(ObjectUtil.isNull(config.getExt1()), SysOssConfig::getExt1, "");
+        luw.set(ObjectUtil.isNull(config.getRemark()), SysOssConfig::getRemark, "");
+        luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId());
+        boolean flag = baseMapper.update(config, luw) > 0;
+        if (flag) {
+            SpringUtils.context().publishEvent(config);
+        }
+        return flag;
+    }
+
+    /**
+     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+     */
+    private void validEntityBeforeSave(SysOssConfig entity) {
+        if (StringUtils.isNotEmpty(entity.getConfigKey())
+            && UserConstants.NOT_UNIQUE.equals(checkConfigKeyUnique(entity))) {
+            throw new ServiceException("鎿嶄綔閰嶇疆'" + entity.getConfigKey() + "'澶辫触, 閰嶇疆key宸插瓨鍦�!");
+        }
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) {
+                throw new ServiceException("绯荤粺鍐呯疆, 涓嶅彲鍒犻櫎!");
+            }
+        }
+        List<SysOssConfig> list = CollUtil.newArrayList();
+        for (Long configId : ids) {
+            SysOssConfig config = baseMapper.selectById(configId);
+            list.add(config);
+        }
+        boolean flag = baseMapper.deleteBatchIds(ids) > 0;
+        if (flag) {
+            list.forEach(sysOssConfig ->
+                CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey()));
+        }
+        return flag;
+    }
+
+    /**
+     * 鍒ゆ柇configKey鏄惁鍞竴
+     */
+    private String checkConfigKeyUnique(SysOssConfig sysOssConfig) {
+        long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId();
+        SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysOssConfig>()
+            .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey)
+            .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey()));
+        if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鍚敤绂佺敤鐘舵��
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateOssConfigStatus(SysOssConfigBo bo) {
+        SysOssConfig sysOssConfig = BeanUtil.toBean(bo, SysOssConfig.class);
+        int row = baseMapper.update(null, new LambdaUpdateWrapper<SysOssConfig>()
+            .set(SysOssConfig::getStatus, "1"));
+        row += baseMapper.updateById(sysOssConfig);
+        if (row > 0) {
+            RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, sysOssConfig.getConfigKey());
+        }
+        return row;
+    }
+
+    /**
+     * 鏇存柊閰嶇疆缂撳瓨
+     *
+     * @param config 閰嶇疆
+     */
+    @EventListener
+    public void updateConfigCache(SysOssConfig config) {
+        CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
+        RedisUtils.publish(OssConstant.DEFAULT_CONFIG_KEY, config.getConfigKey(), msg -> {
+            log.info("鍙戝竷鍒锋柊OSS閰嶇疆 => " + msg);
+        });
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
new file mode 100644
index 0000000..0caf840
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
@@ -0,0 +1,161 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.CacheNames;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.BeanCopyUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.file.FileUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.oss.core.OssClient;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.AccessPolicyType;
+import com.ruoyi.common.oss.factory.OssFactory;
+import com.ruoyi.system.domain.SysOss;
+import com.ruoyi.system.domain.bo.SysOssBo;
+import com.ruoyi.system.domain.vo.SysOssVo;
+import com.ruoyi.system.mapper.SysOssMapper;
+import com.ruoyi.system.service.ISysOssService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 鏂囦欢涓婁紶 鏈嶅姟灞傚疄鐜�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysOssServiceImpl implements ISysOssService {
+
+    private final SysOssMapper baseMapper;
+
+    @Override
+    public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
+        Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        List<SysOssVo> filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList());
+        result.setRecords(filterResult);
+        return TableDataInfo.build(result);
+    }
+
+    @Override
+    public List<SysOssVo> listByIds(Collection<Long> ossIds) {
+        List<SysOssVo> list = new ArrayList<>();
+        for (Long id : ossIds) {
+            SysOssVo vo = SpringUtils.getAopProxy(this).getById(id);
+            if (ObjectUtil.isNotNull(vo)) {
+                list.add(this.matchingUrl(vo));
+            }
+        }
+        return list;
+    }
+
+    private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<SysOss> lqw = Wrappers.lambdaQuery();
+        lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysOss::getFileName, bo.getFileName());
+        lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), SysOss::getOriginalName, bo.getOriginalName());
+        lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), SysOss::getFileSuffix, bo.getFileSuffix());
+        lqw.eq(StringUtils.isNotBlank(bo.getUrl()), SysOss::getUrl, bo.getUrl());
+        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
+            SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
+        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), SysOss::getCreateBy, bo.getCreateBy());
+        lqw.eq(StringUtils.isNotBlank(bo.getService()), SysOss::getService, bo.getService());
+        return lqw;
+    }
+
+    @Cacheable(cacheNames = CacheNames.SYS_OSS, key = "#ossId")
+    @Override
+    public SysOssVo getById(Long ossId) {
+        return baseMapper.selectVoById(ossId);
+    }
+
+    @Override
+    public void download(Long ossId, HttpServletResponse response) throws IOException {
+        SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
+        if (ObjectUtil.isNull(sysOss)) {
+            throw new ServiceException("鏂囦欢鏁版嵁涓嶅瓨鍦�!");
+        }
+        FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
+        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
+        OssClient storage = OssFactory.instance();
+        try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
+            int available = inputStream.available();
+            IoUtil.copy(inputStream, response.getOutputStream(), available);
+            response.setContentLength(available);
+        } catch (Exception e) {
+            throw new ServiceException(e.getMessage());
+        }
+    }
+
+    @Override
+    public SysOssVo upload(MultipartFile file) {
+        String originalfileName = file.getOriginalFilename();
+        String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
+        OssClient storage = OssFactory.instance();
+        UploadResult uploadResult;
+        try {
+            uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
+        } catch (IOException e) {
+            throw new ServiceException(e.getMessage());
+        }
+        // 淇濆瓨鏂囦欢淇℃伅
+        SysOss oss = new SysOss();
+        oss.setUrl(uploadResult.getUrl());
+        oss.setFileSuffix(suffix);
+        oss.setFileName(uploadResult.getFilename());
+        oss.setOriginalName(originalfileName);
+        oss.setService(storage.getConfigKey());
+        baseMapper.insert(oss);
+        SysOssVo sysOssVo = new SysOssVo();
+        BeanCopyUtils.copy(oss, sysOssVo);
+        return this.matchingUrl(sysOssVo);
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            // 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+        }
+        List<SysOss> list = baseMapper.selectBatchIds(ids);
+        for (SysOss sysOss : list) {
+            OssClient storage = OssFactory.instance(sysOss.getService());
+            storage.delete(sysOss.getUrl());
+        }
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+
+    /**
+     * 鍖归厤Url
+     *
+     * @param oss OSS瀵硅薄
+     * @return oss 鍖归厤Url鐨凮SS瀵硅薄
+     */
+    private SysOssVo matchingUrl(SysOssVo oss) {
+        OssClient storage = OssFactory.instance(oss.getService());
+        // 浠呬慨鏀规《绫诲瀷涓� private 鐨刄RL锛屼复鏃禪RL鏃堕暱涓�120s
+        if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
+            oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120));
+        }
+        return oss;
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
new file mode 100644
index 0000000..7d492d1
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
@@ -0,0 +1,184 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.domain.SysUserPost;
+import com.ruoyi.system.mapper.SysPostMapper;
+import com.ruoyi.system.mapper.SysUserPostMapper;
+import com.ruoyi.system.service.ISysPostService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 宀椾綅淇℃伅 鏈嶅姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysPostServiceImpl implements ISysPostService {
+
+    private final SysPostMapper baseMapper;
+    private final SysUserPostMapper userPostMapper;
+
+    @Override
+    public TableDataInfo<SysPost> selectPagePostList(SysPost post, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysPost> lqw = new LambdaQueryWrapper<SysPost>()
+            .like(StringUtils.isNotBlank(post.getPostCode()), SysPost::getPostCode, post.getPostCode())
+            .eq(StringUtils.isNotBlank(post.getStatus()), SysPost::getStatus, post.getStatus())
+            .like(StringUtils.isNotBlank(post.getPostName()), SysPost::getPostName, post.getPostName());
+        Page<SysPost> page = baseMapper.selectPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏌ヨ宀椾綅淇℃伅闆嗗悎
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 宀椾綅淇℃伅闆嗗悎
+     */
+    @Override
+    public List<SysPost> selectPostList(SysPost post) {
+        return baseMapper.selectList(new LambdaQueryWrapper<SysPost>()
+            .like(StringUtils.isNotBlank(post.getPostCode()), SysPost::getPostCode, post.getPostCode())
+            .eq(StringUtils.isNotBlank(post.getStatus()), SysPost::getStatus, post.getStatus())
+            .like(StringUtils.isNotBlank(post.getPostName()), SysPost::getPostName, post.getPostName()));
+    }
+
+    /**
+     * 鏌ヨ鎵�鏈夊矖浣�
+     *
+     * @return 宀椾綅鍒楄〃
+     */
+    @Override
+    public List<SysPost> selectPostAll() {
+        return baseMapper.selectList();
+    }
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+     *
+     * @param postId 宀椾綅ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    @Override
+    public SysPost selectPostById(Long postId) {
+        return baseMapper.selectById(postId);
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑宀椾綅ID鍒楄〃
+     */
+    @Override
+    public List<Long> selectPostListByUserId(Long userId) {
+        return baseMapper.selectPostListByUserId(userId);
+    }
+
+    /**
+     * 鏍¢獙宀椾綅鍚嶇О鏄惁鍞竴
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkPostNameUnique(SysPost post) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>()
+            .eq(SysPost::getPostName, post.getPostName())
+            .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙宀椾綅缂栫爜鏄惁鍞竴
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkPostCodeUnique(SysPost post) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>()
+            .eq(SysPost::getPostCode, post.getPostCode())
+            .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+     *
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public long countUserPostById(Long postId) {
+        return userPostMapper.selectCount(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, postId));
+    }
+
+    /**
+     * 鍒犻櫎宀椾綅淇℃伅
+     *
+     * @param postId 宀椾綅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deletePostById(Long postId) {
+        return baseMapper.deleteById(postId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+     *
+     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deletePostByIds(Long[] postIds) {
+        for (Long postId : postIds) {
+            SysPost post = selectPostById(postId);
+            if (countUserPostById(postId) > 0) {
+                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", post.getPostName()));
+            }
+        }
+        return baseMapper.deleteBatchIds(Arrays.asList(postIds));
+    }
+
+    /**
+     * 鏂板淇濆瓨宀椾綅淇℃伅
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertPost(SysPost post) {
+        return baseMapper.insert(post);
+    }
+
+    /**
+     * 淇敼淇濆瓨宀椾綅淇℃伅
+     *
+     * @param post 宀椾綅淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updatePost(SysPost post) {
+        return baseMapper.updateById(post);
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
new file mode 100644
index 0000000..1c05e4a
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -0,0 +1,412 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+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.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.system.domain.SysRoleDept;
+import com.ruoyi.system.domain.SysRoleMenu;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.mapper.SysRoleDeptMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysRoleMenuMapper;
+import com.ruoyi.system.mapper.SysUserRoleMapper;
+import com.ruoyi.system.service.ISysRoleService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * 瑙掕壊 涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@Service
+public class SysRoleServiceImpl implements ISysRoleService {
+
+    private final SysRoleMapper baseMapper;
+    private final SysRoleMenuMapper roleMenuMapper;
+    private final SysUserRoleMapper userRoleMapper;
+    private final SysRoleDeptMapper roleDeptMapper;
+
+    @Override
+    public TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery) {
+        Page<SysRole> page = baseMapper.selectPageRoleList(pageQuery.build(), this.buildQueryWrapper(role));
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysRole> selectRoleList(SysRole role) {
+        return baseMapper.selectRoleList(this.buildQueryWrapper(role));
+    }
+
+    private Wrapper<SysRole> buildQueryWrapper(SysRole role) {
+        Map<String, Object> params = role.getParams();
+        QueryWrapper<SysRole> wrapper = Wrappers.query();
+        wrapper.eq("r.del_flag", UserConstants.ROLE_NORMAL)
+            .eq(ObjectUtil.isNotNull(role.getRoleId()), "r.role_id", role.getRoleId())
+            .like(StringUtils.isNotBlank(role.getRoleName()), "r.role_name", role.getRoleName())
+            .eq(StringUtils.isNotBlank(role.getStatus()), "r.status", role.getStatus())
+            .like(StringUtils.isNotBlank(role.getRoleKey()), "r.role_key", role.getRoleKey())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                "r.create_time", params.get("beginTime"), params.get("endTime"))
+            .orderByAsc("r.role_sort");
+        return wrapper;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 瑙掕壊鍒楄〃
+     */
+    @Override
+    public List<SysRole> selectRolesByUserId(Long userId) {
+        List<SysRole> userRoles = baseMapper.selectRolePermissionByUserId(userId);
+        List<SysRole> roles = selectRoleAll();
+        for (SysRole role : roles) {
+            for (SysRole userRole : userRoles) {
+                if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) {
+                    role.setFlag(true);
+                    break;
+                }
+            }
+        }
+        return roles;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    @Override
+    public Set<String> selectRolePermissionByUserId(Long userId) {
+        List<SysRole> perms = baseMapper.selectRolePermissionByUserId(userId);
+        Set<String> permsSet = new HashSet<>();
+        for (SysRole perm : perms) {
+            if (ObjectUtil.isNotNull(perm)) {
+                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
+            }
+        }
+        return permsSet;
+    }
+
+    /**
+     * 鏌ヨ鎵�鏈夎鑹�
+     *
+     * @return 瑙掕壊鍒楄〃
+     */
+    @Override
+    public List<SysRole> selectRoleAll() {
+        return this.selectRoleList(new SysRole());
+    }
+
+    /**
+     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 閫変腑瑙掕壊ID鍒楄〃
+     */
+    @Override
+    public List<Long> selectRoleListByUserId(Long userId) {
+        return baseMapper.selectRoleListByUserId(userId);
+    }
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 瑙掕壊瀵硅薄淇℃伅
+     */
+    @Override
+    public SysRole selectRoleById(Long roleId) {
+        return baseMapper.selectById(roleId);
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkRoleNameUnique(SysRole role) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>()
+            .eq(SysRole::getRoleName, role.getRoleName())
+            .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkRoleKeyUnique(SysRole role) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>()
+            .eq(SysRole::getRoleKey, role.getRoleKey())
+            .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
+     *
+     * @param role 瑙掕壊淇℃伅
+     */
+    @Override
+    public void checkRoleAllowed(SysRole role) {
+        if (ObjectUtil.isNotNull(role.getRoleId()) && role.isAdmin()) {
+            throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳瑙掕壊");
+        }
+    }
+
+    /**
+     * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
+     *
+     * @param roleId 瑙掕壊id
+     */
+    @Override
+    public void checkRoleDataScope(Long roleId) {
+        if (!LoginHelper.isAdmin()) {
+            SysRole role = new SysRole();
+            role.setRoleId(roleId);
+            List<SysRole> roles = this.selectRoleList(role);
+            if (CollUtil.isEmpty(roles)) {
+                throw new ServiceException("娌℃湁鏉冮檺璁块棶瑙掕壊鏁版嵁锛�");
+            }
+        }
+    }
+
+    /**
+     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    @Override
+    public long countUserRoleByRoleId(Long roleId) {
+        return userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
+    }
+
+    /**
+     * 鏂板淇濆瓨瑙掕壊淇℃伅
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int insertRole(SysRole role) {
+        // 鏂板瑙掕壊淇℃伅
+        baseMapper.insert(role);
+        return insertRoleMenu(role);
+    }
+
+    /**
+     * 淇敼淇濆瓨瑙掕壊淇℃伅
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateRole(SysRole role) {
+        // 淇敼瑙掕壊淇℃伅
+        baseMapper.updateById(role);
+        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, role.getRoleId()));
+        return insertRoleMenu(role);
+    }
+
+    /**
+     * 淇敼瑙掕壊鐘舵��
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateRoleStatus(SysRole role) {
+        return baseMapper.updateById(role);
+    }
+
+    /**
+     * 淇敼鏁版嵁鏉冮檺淇℃伅
+     *
+     * @param role 瑙掕壊淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int authDataScope(SysRole role) {
+        // 淇敼瑙掕壊淇℃伅
+        baseMapper.updateById(role);
+        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().eq(SysRoleDept::getRoleId, role.getRoleId()));
+        // 鏂板瑙掕壊鍜岄儴闂ㄤ俊鎭紙鏁版嵁鏉冮檺锛�
+        return insertRoleDept(role);
+    }
+
+    /**
+     * 鏂板瑙掕壊鑿滃崟淇℃伅
+     *
+     * @param role 瑙掕壊瀵硅薄
+     */
+    public int insertRoleMenu(SysRole role) {
+        int rows = 1;
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
+        for (Long menuId : role.getMenuIds()) {
+            SysRoleMenu rm = new SysRoleMenu();
+            rm.setRoleId(role.getRoleId());
+            rm.setMenuId(menuId);
+            list.add(rm);
+        }
+        if (list.size() > 0) {
+            rows = roleMenuMapper.insertBatch(list) ? list.size() : 0;
+        }
+        return rows;
+    }
+
+    /**
+     * 鏂板瑙掕壊閮ㄩ棬淇℃伅(鏁版嵁鏉冮檺)
+     *
+     * @param role 瑙掕壊瀵硅薄
+     */
+    public int insertRoleDept(SysRole role) {
+        int rows = 1;
+        // 鏂板瑙掕壊涓庨儴闂紙鏁版嵁鏉冮檺锛夌鐞�
+        List<SysRoleDept> list = new ArrayList<SysRoleDept>();
+        for (Long deptId : role.getDeptIds()) {
+            SysRoleDept rd = new SysRoleDept();
+            rd.setRoleId(role.getRoleId());
+            rd.setDeptId(deptId);
+            list.add(rd);
+        }
+        if (list.size() > 0) {
+            rows = roleDeptMapper.insertBatch(list) ? list.size() : 0;
+        }
+        return rows;
+    }
+
+    /**
+     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+     *
+     * @param roleId 瑙掕壊ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteRoleById(Long roleId) {
+        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
+        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().eq(SysRoleDept::getRoleId, roleId));
+        return baseMapper.deleteById(roleId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+     *
+     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteRoleByIds(Long[] roleIds) {
+        for (Long roleId : roleIds) {
+            checkRoleAllowed(new SysRole(roleId));
+            checkRoleDataScope(roleId);
+            SysRole role = selectRoleById(roleId);
+            if (countUserRoleByRoleId(roleId) > 0) {
+                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", role.getRoleName()));
+            }
+        }
+        List<Long> ids = Arrays.asList(roleIds);
+        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, ids));
+        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().in(SysRoleDept::getRoleId, ids));
+        return baseMapper.deleteBatchIds(ids);
+    }
+
+    /**
+     * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     *
+     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteAuthUser(SysUserRole userRole) {
+        return userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
+            .eq(SysUserRole::getRoleId, userRole.getRoleId())
+            .eq(SysUserRole::getUserId, userRole.getUserId()));
+    }
+
+    /**
+     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+     *
+     * @param roleId  瑙掕壊ID
+     * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteAuthUsers(Long roleId, Long[] userIds) {
+        return userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
+            .eq(SysUserRole::getRoleId, roleId)
+            .in(SysUserRole::getUserId, Arrays.asList(userIds)));
+    }
+
+    /**
+     * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
+     *
+     * @param roleId  瑙掕壊ID
+     * @param userIds 闇�瑕佹巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertAuthUsers(Long roleId, Long[] userIds) {
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        int rows = 1;
+        List<SysUserRole> list = new ArrayList<SysUserRole>();
+        for (Long userId : userIds) {
+            SysUserRole ur = new SysUserRole();
+            ur.setUserId(userId);
+            ur.setRoleId(roleId);
+            list.add(ur);
+        }
+        if (list.size() > 0) {
+            rows = userRoleMapper.insertBatch(list) ? list.size() : 0;
+        }
+        return rows;
+    }
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java
new file mode 100644
index 0000000..2f83e51
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java
@@ -0,0 +1,26 @@
+package com.ruoyi.system.service.impl;
+
+import com.ruoyi.common.core.service.SensitiveService;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import org.springframework.stereotype.Service;
+
+/**
+ * 鑴辨晱鏈嶅姟
+ * 榛樿绠$悊鍛樹笉杩囨护
+ * 闇�鑷鏍规嵁涓氬姟閲嶅啓瀹炵幇
+ *
+ * @author Lion Li
+ * @version 3.6.0
+ */
+@Service
+public class SysSensitiveServiceImpl implements SensitiveService {
+
+    /**
+     * 鏄惁鑴辨晱
+     */
+    @Override
+    public boolean isSensitive() {
+        return !LoginHelper.isAdmin();
+    }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
new file mode 100644
index 0000000..d0df74d
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -0,0 +1,488 @@
+package com.ruoyi.system.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjectUtil;
+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.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.constant.UserConstants;
+import com.ruoyi.common.mybatis.core.page.PageQuery;
+import com.ruoyi.system.domain.SysDept;
+import com.ruoyi.system.domain.SysRole;
+import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.common.mybatis.core.page.TableDataInfo;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.mybatis.helper.DataBaseHelper;
+import com.ruoyi.common.satoken.utils.LoginHelper;
+import com.ruoyi.common.core.utils.StreamUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.domain.SysUserPost;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.service.ISysUserService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鐢ㄦ埛 涓氬姟灞傚鐞�
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class SysUserServiceImpl implements ISysUserService {
+
+    private final SysUserMapper baseMapper;
+    private final SysDeptMapper deptMapper;
+    private final SysRoleMapper roleMapper;
+    private final SysPostMapper postMapper;
+    private final SysUserRoleMapper userRoleMapper;
+    private final SysUserPostMapper userPostMapper;
+
+    @Override
+    public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) {
+        Page<SysUser> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user));
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @Override
+    public List<SysUser> selectUserList(SysUser user) {
+        return baseMapper.selectUserList(this.buildQueryWrapper(user));
+    }
+
+    private Wrapper<SysUser> buildQueryWrapper(SysUser user) {
+        Map<String, Object> params = user.getParams();
+        QueryWrapper<SysUser> wrapper = Wrappers.query();
+        wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
+            .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId())
+            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
+            .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
+            .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber())
+            .between(params.get("beginTime") != null && params.get("endTime") != null,
+                "u.create_time", params.get("beginTime"), params.get("endTime"))
+            .and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
+                List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
+                    .select(SysDept::getDeptId)
+                    .apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors")));
+                List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
+                ids.add(user.getDeptId());
+                w.in("u.dept_id", ids);
+            });
+        return wrapper;
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @Override
+    public TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery) {
+        QueryWrapper<SysUser> wrapper = Wrappers.query();
+        wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
+            .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId())
+            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
+            .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
+            .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
+        Page<SysUser> page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+     */
+    @Override
+    public TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery) {
+        List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId());
+        QueryWrapper<SysUser> wrapper = Wrappers.query();
+        wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
+            .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id"))
+            .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds)
+            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
+            .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
+        Page<SysUser> page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper);
+        return TableDataInfo.build(page);
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    @Override
+    public SysUser selectUserByUserName(String userName) {
+        return baseMapper.selectUserByUserName(userName);
+    }
+
+    /**
+     * 閫氳繃鎵嬫満鍙锋煡璇㈢敤鎴�
+     *
+     * @param phonenumber 鎵嬫満鍙�
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    @Override
+    public SysUser selectUserByPhonenumber(String phonenumber) {
+        return baseMapper.selectUserByPhonenumber(phonenumber);
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 鐢ㄦ埛瀵硅薄淇℃伅
+     */
+    @Override
+    public SysUser selectUserById(Long userId) {
+        return baseMapper.selectUserById(userId);
+    }
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    @Override
+    public String selectUserRoleGroup(String userName) {
+        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
+        if (CollUtil.isEmpty(list)) {
+            return StringUtils.EMPTY;
+        }
+        return StreamUtils.join(list, SysRole::getRoleName);
+    }
+
+    /**
+     * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @return 缁撴灉
+     */
+    @Override
+    public String selectUserPostGroup(String userName) {
+        List<SysPost> list = postMapper.selectPostsByUserName(userName);
+        if (CollUtil.isEmpty(list)) {
+            return StringUtils.EMPTY;
+        }
+        return StreamUtils.join(list, SysPost::getPostName);
+    }
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public String checkUserNameUnique(SysUser user) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
+            .eq(SysUser::getUserName, user.getUserName())
+            .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return
+     */
+    @Override
+    public String checkPhoneUnique(SysUser user) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
+            .eq(SysUser::getPhonenumber, user.getPhonenumber())
+            .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙email鏄惁鍞竴
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return
+     */
+    @Override
+    public String checkEmailUnique(SysUser user) {
+        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
+            .eq(SysUser::getEmail, user.getEmail())
+            .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
+        if (exist) {
+            return UserConstants.NOT_UNIQUE;
+        }
+        return UserConstants.UNIQUE;
+    }
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     */
+    @Override
+    public void checkUserAllowed(SysUser user) {
+        if (ObjectUtil.isNotNull(user.getUserId()) && user.isAdmin()) {
+            throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳鐢ㄦ埛");
+        }
+    }
+
+    /**
+     * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
+     *
+     * @param userId 鐢ㄦ埛id
+     */
+    @Override
+    public void checkUserDataScope(Long userId) {
+        if (!LoginHelper.isAdmin()) {
+            SysUser user = new SysUser();
+            user.setUserId(userId);
+            List<SysUser> users = this.selectUserList(user);
+            if (CollUtil.isEmpty(users)) {
+                throw new ServiceException("娌℃湁鏉冮檺璁块棶鐢ㄦ埛鏁版嵁锛�");
+            }
+        }
+    }
+
+    /**
+     * 鏂板淇濆瓨鐢ㄦ埛淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int insertUser(SysUser user) {
+        // 鏂板鐢ㄦ埛淇℃伅
+        int rows = baseMapper.insert(user);
+        // 鏂板鐢ㄦ埛宀椾綅鍏宠仈
+        insertUserPost(user);
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        insertUserRole(user);
+        return rows;
+    }
+
+    /**
+     * 娉ㄥ唽鐢ㄦ埛淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean registerUser(SysUser user) {
+        user.setCreateBy(user.getUserName());
+        user.setUpdateBy(user.getUserName());
+        return baseMapper.insert(user) > 0;
+    }
+
+    /**
+     * 淇敼淇濆瓨鐢ㄦ埛淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int updateUser(SysUser user) {
+        Long userId = user.getUserId();
+        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
+        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+        insertUserRole(user);
+        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶅叧鑱�
+        userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));
+        // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
+        insertUserPost(user);
+        return baseMapper.updateById(user);
+    }
+
+    /**
+     * 鐢ㄦ埛鎺堟潈瑙掕壊
+     *
+     * @param userId  鐢ㄦ埛ID
+     * @param roleIds 瑙掕壊缁�
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void insertUserAuth(Long userId, Long[] roleIds) {
+        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
+            .eq(SysUserRole::getUserId, userId));
+        insertUserRole(userId, roleIds);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛鐘舵��
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateUserStatus(SysUser user) {
+        return baseMapper.updateById(user);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateUserProfile(SysUser user) {
+        return baseMapper.updateById(user);
+    }
+
+    /**
+     * 淇敼鐢ㄦ埛澶村儚
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @param avatar   澶村儚鍦板潃
+     * @return 缁撴灉
+     */
+    @Override
+    public boolean updateUserAvatar(String userName, String avatar) {
+        return baseMapper.update(null,
+            new LambdaUpdateWrapper<SysUser>()
+                .set(SysUser::getAvatar, avatar)
+                .eq(SysUser::getUserName, userName)) > 0;
+    }
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     *
+     * @param user 鐢ㄦ埛淇℃伅
+     * @return 缁撴灉
+     */
+    @Override
+    public int resetPwd(SysUser user) {
+        return baseMapper.updateById(user);
+    }
+
+    /**
+     * 閲嶇疆鐢ㄦ埛瀵嗙爜
+     *
+     * @param userName 鐢ㄦ埛鍚�
+     * @param password 瀵嗙爜
+     * @return 缁撴灉
+     */
+    @Override
+    public int resetUserPwd(String userName, String password) {
+        return baseMapper.update(null,
+            new LambdaUpdateWrapper<SysUser>()
+                .set(SysUser::getPassword, password)
+                .eq(SysUser::getUserName, userName));
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
+     *
+     * @param user 鐢ㄦ埛瀵硅薄
+     */
+    public void insertUserRole(SysUser user) {
+        this.insertUserRole(user.getUserId(), user.getRoleIds());
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛宀椾綅淇℃伅
+     *
+     * @param user 鐢ㄦ埛瀵硅薄
+     */
+    public void insertUserPost(SysUser user) {
+        Long[] posts = user.getPostIds();
+        if (ArrayUtil.isNotEmpty(posts)) {
+            // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
+            List<SysUserPost> list = new ArrayList<>(posts.length);
+            for (Long postId : posts) {
+                SysUserPost up = new SysUserPost();
+                up.setUserId(user.getUserId());
+                up.setPostId(postId);
+                list.add(up);
+            }
+            userPostMapper.insertBatch(list);
+        }
+    }
+
+    /**
+     * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
+     *
+     * @param userId  鐢ㄦ埛ID
+     * @param roleIds 瑙掕壊缁�
+     */
+    public void insertUserRole(Long userId, Long[] roleIds) {
+        if (ArrayUtil.isNotEmpty(roleIds)) {
+            // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+            List<SysUserRole> list = new ArrayList<>(roleIds.length);
+            for (Long roleId : roleIds) {
+                SysUserRole ur = new SysUserRole();
+                ur.setUserId(userId);
+                ur.setRoleId(roleId);
+                list.add(ur);
+            }
+            userRoleMapper.insertBatch(list);
+        }
+    }
+
+    /**
+     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+     *
+     * @param userId 鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteUserById(Long userId) {
+        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
+        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶈〃
+        userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));
+        return baseMapper.deleteById(userId);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+     *
+     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+     * @return 缁撴灉
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteUserByIds(Long[] userIds) {
+        for (Long userId : userIds) {
+            checkUserAllowed(new SysUser(userId));
+            checkUserDataScope(userId);
+        }
+        List<Long> ids = Arrays.asList(userIds);
+        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));
+        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶈〃
+        userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().in(SysUserPost::getUserId, ids));
+        return baseMapper.deleteBatchIds(ids);
+    }
+
+}
diff --git a/ruoyi-system/src/main/resources/mapper/package-info.md b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/package-info.md
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/package-info.md
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/package-info.md
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysOssConfigMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssConfigMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysOssConfigMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssConfigMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysOssMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysOssMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
similarity index 100%
rename from ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
rename to ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
diff --git a/ruoyi-oss/pom.xml b/ruoyi-oss/pom.xml
deleted file mode 100644
index 4ff84b6..0000000
--- a/ruoyi-oss/pom.xml
+++ /dev/null
@@ -1,34 +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>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-oss</artifactId>
-
-    <description>
-        OSS瀵硅薄瀛樺偍妯″潡
-    </description>
-
-    <dependencies>
-
-        <!-- 閫氱敤宸ュ叿-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.amazonaws</groupId>
-            <artifactId>aws-java-sdk-s3</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java
deleted file mode 100644
index 06202d0..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.ruoyi.oss.constant;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 瀵硅薄瀛樺偍甯搁噺
- *
- * @author Lion Li
- */
-public interface OssConstant {
-
-    /**
-     * 榛樿閰嶇疆KEY
-     */
-    String DEFAULT_CONFIG_KEY = "sys_oss:default_config";
-
-    /**
-     * 棰勮鍒楄〃璧勬簮寮�鍏矺ey
-     */
-    String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
-
-    /**
-     * 绯荤粺鏁版嵁ids
-     */
-    List<Long> SYSTEM_DATA_IDS = Arrays.asList(1L, 2L, 3L, 4L);
-
-    /**
-     * 浜戞湇鍔″晢
-     */
-    String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu", "obs"};
-
-    /**
-     * https 鐘舵��
-     */
-    String IS_HTTPS = "Y";
-
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java
deleted file mode 100644
index fe409ce..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package com.ruoyi.oss.core;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.IdUtil;
-import com.amazonaws.ClientConfiguration;
-import com.amazonaws.HttpMethod;
-import com.amazonaws.Protocol;
-import com.amazonaws.auth.AWSCredentials;
-import com.amazonaws.auth.AWSCredentialsProvider;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.BasicAWSCredentials;
-import com.amazonaws.client.builder.AwsClientBuilder;
-import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.AmazonS3Client;
-import com.amazonaws.services.s3.AmazonS3ClientBuilder;
-import com.amazonaws.services.s3.model.*;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.oss.constant.OssConstant;
-import com.ruoyi.oss.entity.UploadResult;
-import com.ruoyi.oss.enumd.AccessPolicyType;
-import com.ruoyi.oss.enumd.PolicyType;
-import com.ruoyi.oss.exception.OssException;
-import com.ruoyi.oss.properties.OssProperties;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Date;
-
-/**
- * S3 瀛樺偍鍗忚 鎵�鏈夊吋瀹筍3鍗忚鐨勪簯鍘傚晢鍧囨敮鎸�
- * 闃块噷浜� 鑵捐浜� 涓冪墰浜� minio
- *
- * @author Lion Li
- */
-public class OssClient {
-
-    private final String configKey;
-
-    private final OssProperties properties;
-
-    private final AmazonS3 client;
-
-    public OssClient(String configKey, OssProperties ossProperties) {
-        this.configKey = configKey;
-        this.properties = ossProperties;
-        try {
-            AwsClientBuilder.EndpointConfiguration endpointConfig =
-                new AwsClientBuilder.EndpointConfiguration(properties.getEndpoint(), properties.getRegion());
-
-            AWSCredentials credentials = new BasicAWSCredentials(properties.getAccessKey(), properties.getSecretKey());
-            AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);
-            ClientConfiguration clientConfig = new ClientConfiguration();
-            if (OssConstant.IS_HTTPS.equals(properties.getIsHttps())) {
-                clientConfig.setProtocol(Protocol.HTTPS);
-            } else {
-                clientConfig.setProtocol(Protocol.HTTP);
-            }
-            AmazonS3ClientBuilder build = AmazonS3Client.builder()
-                .withEndpointConfiguration(endpointConfig)
-                .withClientConfiguration(clientConfig)
-                .withCredentials(credentialsProvider)
-                .disableChunkedEncoding();
-            if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) {
-                // minio 浣跨敤https闄愬埗浣跨敤鍩熷悕璁块棶 闇�瑕佹閰嶇疆 绔欑偣濉煙鍚�
-                build.enablePathStyleAccess();
-            }
-            this.client = build.build();
-
-            createBucket();
-        } catch (Exception e) {
-            if (e instanceof OssException) {
-                throw e;
-            }
-            throw new OssException("閰嶇疆閿欒! 璇锋鏌ョ郴缁熼厤缃�:[" + e.getMessage() + "]");
-        }
-    }
-
-    public void createBucket() {
-        try {
-            String bucketName = properties.getBucketName();
-            if (client.doesBucketExistV2(bucketName)) {
-                return;
-            }
-            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
-            AccessPolicyType accessPolicy = getAccessPolicy();
-            createBucketRequest.setCannedAcl(accessPolicy.getAcl());
-            client.createBucket(createBucketRequest);
-            client.setBucketPolicy(bucketName, getPolicy(bucketName, accessPolicy.getPolicyType()));
-        } catch (Exception e) {
-            throw new OssException("鍒涘缓Bucket澶辫触, 璇锋牳瀵归厤缃俊鎭�:[" + e.getMessage() + "]");
-        }
-    }
-
-    public UploadResult upload(byte[] data, String path, String contentType) {
-        return upload(new ByteArrayInputStream(data), path, contentType);
-    }
-
-    public UploadResult upload(InputStream inputStream, String path, String contentType) {
-        if (!(inputStream instanceof ByteArrayInputStream)) {
-            inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
-        }
-        try {
-            ObjectMetadata metadata = new ObjectMetadata();
-            metadata.setContentType(contentType);
-            metadata.setContentLength(inputStream.available());
-            PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata);
-            // 璁剧疆涓婁紶瀵硅薄鐨� Acl 涓哄叕鍏辫
-            putObjectRequest.setCannedAcl(getAccessPolicy().getAcl());
-            client.putObject(putObjectRequest);
-        } catch (Exception e) {
-            throw new OssException("涓婁紶鏂囦欢澶辫触锛岃妫�鏌ラ厤缃俊鎭�:[" + e.getMessage() + "]");
-        }
-        return UploadResult.builder().url(getUrl() + "/" + path).filename(path).build();
-    }
-
-    public void delete(String path) {
-        path = path.replace(getUrl() + "/", "");
-        try {
-            client.deleteObject(properties.getBucketName(), path);
-        } catch (Exception e) {
-            throw new OssException("鍒犻櫎鏂囦欢澶辫触锛岃妫�鏌ラ厤缃俊鎭�:[" + e.getMessage() + "]");
-        }
-    }
-
-    public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
-        return upload(data, getPath(properties.getPrefix(), suffix), contentType);
-    }
-
-    public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
-        return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
-    }
-
-    /**
-     * 鑾峰彇鏂囦欢鍏冩暟鎹�
-     *
-     * @param path 瀹屾暣鏂囦欢璺緞
-     */
-    public ObjectMetadata getObjectMetadata(String path) {
-        path = path.replace(getUrl() + "/", "");
-        S3Object object = client.getObject(properties.getBucketName(), path);
-        return object.getObjectMetadata();
-    }
-
-    public InputStream getObjectContent(String path) {
-        path = path.replace(getUrl() + "/", "");
-        S3Object object = client.getObject(properties.getBucketName(), path);
-        return object.getObjectContent();
-    }
-
-    public String getUrl() {
-        String domain = properties.getDomain();
-        String endpoint = properties.getEndpoint();
-        String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://";
-        // 浜戞湇鍔″晢鐩存帴杩斿洖
-        if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) {
-            if (StringUtils.isNotBlank(domain)) {
-                return header + domain;
-            }
-            return header + properties.getBucketName() + "." + endpoint;
-        }
-        // minio 鍗曠嫭澶勭悊
-        if (StringUtils.isNotBlank(domain)) {
-            return header + domain + "/" + properties.getBucketName();
-        }
-        return header + endpoint + "/" + properties.getBucketName();
-    }
-
-    public String getPath(String prefix, String suffix) {
-        // 鐢熸垚uuid
-        String uuid = IdUtil.fastSimpleUUID();
-        // 鏂囦欢璺緞
-        String path = DateUtils.datePath() + "/" + uuid;
-        if (StringUtils.isNotBlank(prefix)) {
-            path = prefix + "/" + path;
-        }
-        return path + suffix;
-    }
-
-
-    public String getConfigKey() {
-        return configKey;
-    }
-
-    public String getPrivateUrl(String objectKey, Integer second) {
-        GeneratePresignedUrlRequest generatePresignedUrlRequest =
-            new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
-                .withMethod(HttpMethod.GET)
-                .withExpiration(new Date(System.currentTimeMillis() + 1000L * second));
-        URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
-        return url.toString();
-    }
-
-    /**
-     * 鑾峰彇褰撳墠妗舵潈闄愮被鍨�
-     *
-     * @return 褰撳墠妗舵潈闄愮被鍨媍ode
-     */
-    public AccessPolicyType getAccessPolicy() {
-        return AccessPolicyType.getByType(properties.getAccessPolicy());
-    }
-
-    private static String getPolicy(String bucketName, PolicyType policyType) {
-        StringBuilder builder = new StringBuilder();
-        builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n");
-        if (policyType == PolicyType.WRITE) {
-            builder.append("\"s3:GetBucketLocation\",\n\"s3:ListBucketMultipartUploads\"\n");
-        } else if (policyType == PolicyType.READ_WRITE) {
-            builder.append("\"s3:GetBucketLocation\",\n\"s3:ListBucket\",\n\"s3:ListBucketMultipartUploads\"\n");
-        } else {
-            builder.append("\"s3:GetBucketLocation\"\n");
-        }
-        builder.append("],\n\"Effect\": \"Allow\",\n\"Principal\": \"*\",\n\"Resource\": \"arn:aws:s3:::");
-        builder.append(bucketName);
-        builder.append("\"\n},\n");
-        if (policyType == PolicyType.READ) {
-            builder.append("{\n\"Action\": [\n\"s3:ListBucket\"\n],\n\"Effect\": \"Deny\",\n\"Principal\": \"*\",\n\"Resource\": \"arn:aws:s3:::");
-            builder.append(bucketName);
-            builder.append("\"\n},\n");
-        }
-        builder.append("{\n\"Action\": ");
-        switch (policyType) {
-            case WRITE:
-                builder.append("[\n\"s3:AbortMultipartUpload\",\n\"s3:DeleteObject\",\n\"s3:ListMultipartUploadParts\",\n\"s3:PutObject\"\n],\n");
-                break;
-            case READ_WRITE:
-                builder.append("[\n\"s3:AbortMultipartUpload\",\n\"s3:DeleteObject\",\n\"s3:GetObject\",\n\"s3:ListMultipartUploadParts\",\n\"s3:PutObject\"\n],\n");
-                break;
-            default:
-                builder.append("\"s3:GetObject\",\n");
-                break;
-        }
-        builder.append("\"Effect\": \"Allow\",\n\"Principal\": \"*\",\n\"Resource\": \"arn:aws:s3:::");
-        builder.append(bucketName);
-        builder.append("/*\"\n}\n],\n\"Version\": \"2012-10-17\"\n}\n");
-        return builder.toString();
-    }
-
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/entity/UploadResult.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/entity/UploadResult.java
deleted file mode 100644
index 379d283..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/entity/UploadResult.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.oss.entity;
-
-import lombok.Builder;
-import lombok.Data;
-
-/**
- * 涓婁紶杩斿洖浣�
- *
- * @author Lion Li
- */
-@Data
-@Builder
-public class UploadResult {
-
-    /**
-     * 鏂囦欢璺緞
-     */
-    private String url;
-
-    /**
-     * 鏂囦欢鍚�
-     */
-    private String filename;
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java
deleted file mode 100644
index 1cae670..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.ruoyi.oss.enumd;
-
-import com.amazonaws.services.s3.model.CannedAccessControlList;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 妗惰闂瓥鐣ラ厤缃�
- *
- * @author 闄堣碀
- */
-@Getter
-@AllArgsConstructor
-public enum AccessPolicyType {
-
-    /**
-     * private
-     */
-    PRIVATE("0", CannedAccessControlList.Private, PolicyType.WRITE),
-
-    /**
-     * public
-     */
-    PUBLIC("1", CannedAccessControlList.PublicRead, PolicyType.READ),
-
-    /**
-     * custom
-     */
-    CUSTOM("2",CannedAccessControlList.PublicRead, PolicyType.READ);
-
-    /**
-     * 妗� 鏉冮檺绫诲瀷
-     */
-    private final String type;
-
-    /**
-     * 鏂囦欢瀵硅薄 鏉冮檺绫诲瀷
-     */
-    private final CannedAccessControlList acl;
-
-    /**
-     * 妗剁瓥鐣ョ被鍨�
-     */
-    private final PolicyType policyType;
-
-    public static AccessPolicyType getByType(String type) {
-        for (AccessPolicyType value : values()) {
-            if (value.getType().equals(type)) {
-                return value;
-            }
-        }
-        throw new RuntimeException("'type' not found By " + type);
-    }
-
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/PolicyType.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/PolicyType.java
deleted file mode 100644
index 606f0f4..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/PolicyType.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.ruoyi.oss.enumd;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * minio绛栫暐閰嶇疆
- *
- * @author Lion Li
- */
-@Getter
-@AllArgsConstructor
-public enum PolicyType {
-
-    /**
-     * 鍙
-     */
-    READ("read-only"),
-
-    /**
-     * 鍙啓
-     */
-    WRITE("write-only"),
-
-    /**
-     * 璇诲啓
-     */
-    READ_WRITE("read-write");
-
-    /**
-     * 绫诲瀷
-     */
-    private final String type;
-
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/exception/OssException.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/exception/OssException.java
deleted file mode 100644
index c170297..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/exception/OssException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ruoyi.oss.exception;
-
-import java.io.Serial;
-
-/**
- * OSS寮傚父绫�
- *
- * @author Lion Li
- */
-public class OssException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public OssException(String msg) {
-        super(msg);
-    }
-
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java
deleted file mode 100644
index c3312d7..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.ruoyi.oss.factory;
-
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.oss.constant.OssConstant;
-import com.ruoyi.oss.core.OssClient;
-import com.ruoyi.oss.exception.OssException;
-import com.ruoyi.oss.properties.OssProperties;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * 鏂囦欢涓婁紶Factory
- *
- * @author Lion Li
- */
-@Slf4j
-public class OssFactory {
-
-    private static final Map<String, OssClient> CLIENT_CACHE = new ConcurrentHashMap<>();
-
-    /**
-     * 鍒濆鍖栧伐鍘�
-     */
-    public static void init() {
-        log.info("鍒濆鍖朞SS宸ュ巶");
-        RedisUtils.subscribe(OssConstant.DEFAULT_CONFIG_KEY, String.class, configKey -> {
-            OssClient client = getClient(configKey);
-            // 鏈垵濮嬪寲涓嶅鐞�
-            if (client != null) {
-                refresh(configKey);
-                log.info("璁㈤槄鍒锋柊OSS閰嶇疆 => " + configKey);
-            }
-        });
-    }
-
-    /**
-     * 鑾峰彇榛樿瀹炰緥
-     */
-    public static OssClient instance() {
-        // 鑾峰彇redis 榛樿绫诲瀷
-        String configKey = RedisUtils.getCacheObject(OssConstant.DEFAULT_CONFIG_KEY);
-        if (StringUtils.isEmpty(configKey)) {
-            throw new OssException("鏂囦欢瀛樺偍鏈嶅姟绫诲瀷鏃犳硶鎵惧埌!");
-        }
-        return instance(configKey);
-    }
-
-    /**
-     * 鏍规嵁绫诲瀷鑾峰彇瀹炰緥
-     */
-    public static OssClient instance(String configKey) {
-        OssClient client = getClient(configKey);
-        if (client == null) {
-            refresh(configKey);
-            return getClient(configKey);
-        }
-        return client;
-    }
-
-    private static void refresh(String configKey) {
-        String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey);
-        if (json == null) {
-            throw new OssException("绯荤粺寮傚父, '" + configKey + "'閰嶇疆淇℃伅涓嶅瓨鍦�!");
-        }
-        OssProperties properties = JsonUtils.parseObject(json, OssProperties.class);
-        CLIENT_CACHE.put(configKey, new OssClient(configKey, properties));
-    }
-
-    private static OssClient getClient(String configKey) {
-        return CLIENT_CACHE.get(configKey);
-    }
-
-}
diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java
deleted file mode 100644
index 781a170..0000000
--- a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.ruoyi.oss.properties;
-
-import lombok.Data;
-
-/**
- * OSS瀵硅薄瀛樺偍 閰嶇疆灞炴��
- *
- * @author Lion Li
- */
-@Data
-public class OssProperties {
-
-    /**
-     * 璁块棶绔欑偣
-     */
-    private String endpoint;
-
-    /**
-     * 鑷畾涔夊煙鍚�
-     */
-    private String domain;
-
-    /**
-     * 鍓嶇紑
-     */
-    private String prefix;
-
-    /**
-     * ACCESS_KEY
-     */
-    private String accessKey;
-
-    /**
-     * SECRET_KEY
-     */
-    private String secretKey;
-
-    /**
-     * 瀛樺偍绌洪棿鍚�
-     */
-    private String bucketName;
-
-    /**
-     * 瀛樺偍鍖哄煙
-     */
-    private String region;
-
-    /**
-     * 鏄惁https锛圷=鏄�,N=鍚︼級
-     */
-    private String isHttps;
-
-    /**
-     * 妗舵潈闄愮被鍨�(0private 1public 2custom)
-     */
-    private String accessPolicy;
-
-}
diff --git a/ruoyi-sms/pom.xml b/ruoyi-sms/pom.xml
deleted file mode 100644
index 66e5fb7..0000000
--- a/ruoyi-sms/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>
-        <artifactId>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-sms</artifactId>
-
-    <description>
-        SMS鐭俊妯″潡
-    </description>
-
-    <dependencies>
-
-        <!-- 閫氱敤宸ュ叿-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.aliyun</groupId>
-            <artifactId>dysmsapi20170525</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>com.tencentcloudapi</groupId>
-            <artifactId>tencentcloud-sdk-java-sms</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java
deleted file mode 100644
index 753773e..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.ruoyi.sms.config;
-
-import com.ruoyi.sms.config.properties.SmsProperties;
-import com.ruoyi.sms.core.AliyunSmsTemplate;
-import com.ruoyi.sms.core.SmsTemplate;
-import com.ruoyi.sms.core.TencentSmsTemplate;
-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;
-
-/**
- * 鐭俊閰嶇疆绫�
- *
- * @author Lion Li
- * @version 4.2.0
- */
-@Configuration
-public class SmsConfig {
-
-    @Configuration
-    @ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
-    @ConditionalOnClass(com.aliyun.dysmsapi20170525.Client.class)
-    static class AliyunSmsConfig {
-
-        @Bean
-        public SmsTemplate aliyunSmsTemplate(SmsProperties smsProperties) {
-            return new AliyunSmsTemplate(smsProperties);
-        }
-
-    }
-
-    @Configuration
-    @ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
-    @ConditionalOnClass(com.tencentcloudapi.sms.v20190711.SmsClient.class)
-    static class TencentSmsConfig {
-
-        @Bean
-        public SmsTemplate tencentSmsTemplate(SmsProperties smsProperties) {
-            return new TencentSmsTemplate(smsProperties);
-        }
-
-    }
-
-}
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java
deleted file mode 100644
index 39359cd..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.sms.config.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * SMS鐭俊 閰嶇疆灞炴��
- *
- * @author Lion Li
- * @version 4.2.0
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "sms")
-public class SmsProperties {
-
-    private Boolean enabled;
-
-    /**
-     * 閰嶇疆鑺傜偣
-     * 闃块噷浜� dysmsapi.aliyuncs.com
-     * 鑵捐浜� sms.tencentcloudapi.com
-     */
-    private String endpoint;
-
-    /**
-     * key
-     */
-    private String accessKeyId;
-
-    /**
-     * 瀵嗗寵
-     */
-    private String accessKeySecret;
-
-    /*
-     * 鐭俊绛惧悕
-     */
-    private String signName;
-
-    /**
-     * 鐭俊搴旂敤ID (鑵捐涓撳睘)
-     */
-    private String sdkAppId;
-
-}
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java
deleted file mode 100644
index 3c16a5b..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.ruoyi.sms.core;
-
-import com.aliyun.dysmsapi20170525.Client;
-import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
-import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
-import com.aliyun.teaopenapi.models.Config;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.sms.config.properties.SmsProperties;
-import com.ruoyi.sms.entity.SmsResult;
-import com.ruoyi.sms.exception.SmsException;
-import lombok.SneakyThrows;
-
-import java.util.Map;
-
-/**
- * Aliyun 鐭俊妯℃澘
- *
- * @author Lion Li
- * @version 4.2.0
- */
-public class AliyunSmsTemplate implements SmsTemplate {
-
-    private SmsProperties properties;
-
-    private Client client;
-
-    @SneakyThrows(Exception.class)
-    public AliyunSmsTemplate(SmsProperties smsProperties) {
-        this.properties = smsProperties;
-        Config config = new Config()
-            // 鎮ㄧ殑AccessKey ID
-            .setAccessKeyId(smsProperties.getAccessKeyId())
-            // 鎮ㄧ殑AccessKey Secret
-            .setAccessKeySecret(smsProperties.getAccessKeySecret())
-            // 璁块棶鐨勫煙鍚�
-            .setEndpoint(smsProperties.getEndpoint());
-        this.client = new Client(config);
-    }
-
-    @Override
-    public SmsResult send(String phones, String templateId, Map<String, String> param) {
-        if (StringUtils.isBlank(phones)) {
-            throw new SmsException("鎵嬫満鍙蜂笉鑳戒负绌�");
-        }
-        if (StringUtils.isBlank(templateId)) {
-            throw new SmsException("妯℃澘ID涓嶈兘涓虹┖");
-        }
-        SendSmsRequest req = new SendSmsRequest()
-            .setPhoneNumbers(phones)
-            .setSignName(properties.getSignName())
-            .setTemplateCode(templateId)
-            .setTemplateParam(JsonUtils.toJsonString(param));
-        try {
-            SendSmsResponse resp = client.sendSms(req);
-            return SmsResult.builder()
-                .isSuccess("OK".equals(resp.getBody().getCode()))
-                .message(resp.getBody().getMessage())
-                .response(JsonUtils.toJsonString(resp))
-                .build();
-        } catch (Exception e) {
-            throw new SmsException(e.getMessage());
-        }
-    }
-
-}
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java
deleted file mode 100644
index 0aec3dd..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.sms.core;
-
-import com.ruoyi.sms.entity.SmsResult;
-
-import java.util.Map;
-
-/**
- * 鐭俊妯℃澘
- *
- * @author Lion Li
- * @version 4.2.0
- */
-public interface SmsTemplate {
-
-    /**
-     * 鍙戦�佺煭淇�
-     *
-     * @param phones     鐢佃瘽鍙�(澶氫釜閫楀彿鍒嗗壊)
-     * @param templateId 妯℃澘id
-     * @param param      妯℃澘瀵瑰簲鍙傛暟
-     *                   闃块噷 闇�浣跨敤 妯℃澘鍙橀噺鍚嶇О瀵瑰簲鍐呭 渚嬪: code=1234
-     *                   鑵捐 闇�浣跨敤 妯℃澘鍙橀噺椤哄簭瀵瑰簲鍐呭 渚嬪: 1=1234, 1涓烘ā鏉垮唴绗竴涓弬鏁�
-     */
-    SmsResult send(String phones, String templateId, Map<String, String> param);
-
-}
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java
deleted file mode 100644
index 17f5b5b..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.ruoyi.sms.core;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.sms.config.properties.SmsProperties;
-import com.ruoyi.sms.entity.SmsResult;
-import com.ruoyi.sms.exception.SmsException;
-import com.tencentcloudapi.common.Credential;
-import com.tencentcloudapi.common.profile.ClientProfile;
-import com.tencentcloudapi.common.profile.HttpProfile;
-import com.tencentcloudapi.sms.v20190711.SmsClient;
-import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
-import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
-import com.tencentcloudapi.sms.v20190711.models.SendStatus;
-import lombok.SneakyThrows;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Tencent 鐭俊妯℃澘
- *
- * @author Lion Li
- * @version 4.2.0
- */
-public class TencentSmsTemplate implements SmsTemplate {
-
-    private SmsProperties properties;
-
-    private SmsClient client;
-
-    @SneakyThrows(Exception.class)
-    public TencentSmsTemplate(SmsProperties smsProperties) {
-        this.properties = smsProperties;
-        Credential credential = new Credential(smsProperties.getAccessKeyId(), smsProperties.getAccessKeySecret());
-        HttpProfile httpProfile = new HttpProfile();
-        httpProfile.setEndpoint(smsProperties.getEndpoint());
-        ClientProfile clientProfile = new ClientProfile();
-        clientProfile.setHttpProfile(httpProfile);
-        this.client = new SmsClient(credential, "", clientProfile);
-    }
-
-    @Override
-    public SmsResult send(String phones, String templateId, Map<String, String> param) {
-        if (StringUtils.isBlank(phones)) {
-            throw new SmsException("鎵嬫満鍙蜂笉鑳戒负绌�");
-        }
-        if (StringUtils.isBlank(templateId)) {
-            throw new SmsException("妯℃澘ID涓嶈兘涓虹┖");
-        }
-        SendSmsRequest req = new SendSmsRequest();
-        Set<String> set = Arrays.stream(phones.split(",")).map(p -> "+86" + p).collect(Collectors.toSet());
-        req.setPhoneNumberSet(ArrayUtil.toArray(set, String.class));
-        if (CollUtil.isNotEmpty(param)) {
-            req.setTemplateParamSet(ArrayUtil.toArray(param.values(), String.class));
-        }
-        req.setTemplateID(templateId);
-        req.setSign(properties.getSignName());
-        req.setSmsSdkAppid(properties.getSdkAppId());
-        try {
-            SendSmsResponse resp = client.SendSms(req);
-            SmsResult.SmsResultBuilder builder = SmsResult.builder()
-                .isSuccess(true)
-                .message("send success")
-                .response(JsonUtils.toJsonString(resp));
-            for (SendStatus sendStatus : resp.getSendStatusSet()) {
-                if (!"Ok".equals(sendStatus.getCode())) {
-                    builder.isSuccess(false).message(sendStatus.getMessage());
-                    break;
-                }
-            }
-            return builder.build();
-        } catch (Exception e) {
-            throw new SmsException(e.getMessage());
-        }
-    }
-
-}
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java
deleted file mode 100644
index 89c39b4..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.ruoyi.sms.entity;
-
-import lombok.Builder;
-import lombok.Data;
-
-/**
- * 涓婁紶杩斿洖浣�
- *
- * @author Lion Li
- */
-@Data
-@Builder
-public class SmsResult {
-
-    /**
-     * 鏄惁鎴愬姛
-     */
-    private boolean isSuccess;
-
-    /**
-     * 鍝嶅簲娑堟伅
-     */
-    private String message;
-
-    /**
-     * 瀹為檯鍝嶅簲浣�
-     * <p>
-     * 鍙嚜琛岃浆鎹负 SDK 瀵瑰簲鐨� SendSmsResponse
-     */
-    private String response;
-}
diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java
deleted file mode 100644
index 006babc..0000000
--- a/ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ruoyi.sms.exception;
-
-import java.io.Serial;
-
-/**
- * Sms寮傚父绫�
- *
- * @author Lion Li
- */
-public class SmsException extends RuntimeException {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    public SmsException(String msg) {
-        super(msg);
-    }
-
-}
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
deleted file mode 100644
index 3e9e680..0000000
--- a/ruoyi-system/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>
-        <artifactId>ruoyi-vue-plus</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>${revision}</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-system</artifactId>
-
-    <description>
-        system绯荤粺妯″潡
-    </description>
-
-    <dependencies>
-
-        <!-- 閫氱敤宸ュ叿-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-common</artifactId>
-        </dependency>
-
-        <!-- OSS鍔熻兘妯″潡 -->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-oss</artifactId>
-        </dependency>
-
-        <!-- SMS鍔熻兘妯″潡 -->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-sms</artifactId>
-        </dependency>
-
-    </dependencies>
-
-</project>
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java
deleted file mode 100644
index 26895d2..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/CacheController.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package com.ruoyi.system.controller.monitor;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.collection.CollUtil;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.system.domain.SysCache;
-import lombok.RequiredArgsConstructor;
-import org.redisson.spring.data.connection.RedissonConnectionFactory;
-import org.springframework.data.redis.connection.RedisConnection;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 缂撳瓨鐩戞帶
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/monitor/cache")
-public class CacheController {
-
-    private final RedissonConnectionFactory connectionFactory;
-
-    private final static List<SysCache> CACHES = new ArrayList<>();
-
-    static {
-        CACHES.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "鐢ㄦ埛淇℃伅"));
-        CACHES.add(new SysCache(CacheConstants.ONLINE_TOKEN_KEY, "鍦ㄧ嚎鐢ㄦ埛"));
-        CACHES.add(new SysCache(CacheNames.SYS_CONFIG, "閰嶇疆淇℃伅"));
-        CACHES.add(new SysCache(CacheNames.SYS_DICT, "鏁版嵁瀛楀吀"));
-        CACHES.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "楠岃瘉鐮�"));
-        CACHES.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "闃查噸鎻愪氦"));
-        CACHES.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "闄愭祦澶勭悊"));
-        CACHES.add(new SysCache(CacheNames.SYS_OSS_CONFIG, "OSS閰嶇疆"));
-        CACHES.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "瀵嗙爜閿欒娆℃暟"));
-    }
-
-    /**
-     * 鑾峰彇缂撳瓨鐩戞帶鍒楄〃
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @GetMapping()
-    public R<Map<String, Object>> getInfo() throws Exception {
-        RedisConnection connection = connectionFactory.getConnection();
-        Properties info = connection.commands().info();
-        Properties commandStats = connection.commands().info("commandstats");
-        Long dbSize = connection.commands().dbSize();
-
-        Map<String, Object> result = new HashMap<>(3);
-        result.put("info", info);
-        result.put("dbSize", dbSize);
-
-        List<Map<String, String>> pieList = new ArrayList<>();
-        if (commandStats != null) {
-            commandStats.stringPropertyNames().forEach(key -> {
-                Map<String, String> data = new HashMap<>(2);
-                String property = commandStats.getProperty(key);
-                data.put("name", StringUtils.removeStart(key, "cmdstat_"));
-                data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
-                pieList.add(data);
-            });
-        }
-        result.put("commandStats", pieList);
-        return R.ok(result);
-    }
-
-    /**
-     * 鑾峰彇缂撳瓨鐩戞帶缂撳瓨鍚嶅垪琛�
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @GetMapping("/getNames")
-    public R<List<SysCache>> cache() {
-        return R.ok(CACHES);
-    }
-
-    /**
-     * 鑾峰彇缂撳瓨鐩戞帶Key鍒楄〃
-     *
-     * @param cacheName 缂撳瓨鍚�
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @GetMapping("/getKeys/{cacheName}")
-    public R<Collection<String>> getCacheKeys(@PathVariable String cacheName) {
-        Collection<String> cacheKeys = new HashSet<>(0);
-        if (isCacheNames(cacheName)) {
-            Set<Object> keys = CacheUtils.keys(cacheName);
-            if (CollUtil.isNotEmpty(keys)) {
-                cacheKeys = keys.stream().map(Object::toString).collect(Collectors.toList());
-            }
-        } else {
-            cacheKeys = RedisUtils.keys(cacheName + "*");
-        }
-        return R.ok(cacheKeys);
-    }
-
-    /**
-     * 鑾峰彇缂撳瓨鐩戞帶缂撳瓨鍊艰鎯�
-     *
-     * @param cacheName 缂撳瓨鍚�
-     * @param cacheKey  缂撳瓨key
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @GetMapping("/getValue/{cacheName}/{cacheKey}")
-    public R<SysCache> getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) {
-        Object cacheValue;
-        if (isCacheNames(cacheName)) {
-            cacheValue = CacheUtils.get(cacheName, cacheKey);
-        } else {
-            cacheValue = RedisUtils.getCacheObject(cacheKey);
-        }
-        SysCache sysCache = new SysCache(cacheName, cacheKey, JsonUtils.toJsonString(cacheValue));
-        return R.ok(sysCache);
-    }
-
-    /**
-     * 娓呯悊缂撳瓨鐩戞帶缂撳瓨鍚�
-     *
-     * @param cacheName 缂撳瓨鍚�
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @DeleteMapping("/clearCacheName/{cacheName}")
-    public R<Void> clearCacheName(@PathVariable String cacheName) {
-        if (isCacheNames(cacheName)) {
-            CacheUtils.clear(cacheName);
-        } else {
-            RedisUtils.deleteKeys(cacheName + "*");
-        }
-        return R.ok();
-    }
-
-    /**
-     * 娓呯悊缂撳瓨鐩戞帶Key
-     *
-     * @param cacheKey key鍚�
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @DeleteMapping("/clearCacheKey/{cacheName}/{cacheKey}")
-    public R<Void> clearCacheKey(@PathVariable String cacheName, @PathVariable String cacheKey) {
-        if (isCacheNames(cacheName)) {
-            CacheUtils.evict(cacheName, cacheKey);
-        } else {
-            RedisUtils.deleteObject(cacheKey);
-        }
-        return R.ok();
-    }
-
-    /**
-     * 娓呯悊鍏ㄩ儴缂撳瓨鐩戞帶
-     */
-    @SaCheckPermission("monitor:cache:list")
-    @DeleteMapping("/clearCacheAll")
-    public R<Void> clearCacheAll() {
-        RedisUtils.deleteKeys("*");
-        return R.ok();
-    }
-
-    private boolean isCacheNames(String cacheName) {
-        return !StringUtils.contains(cacheName, ":");
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java
deleted file mode 100644
index 8b15a50..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysLogininforController.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.ruoyi.system.controller.monitor;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.system.domain.SysLogininfor;
-import com.ruoyi.system.service.ISysLogininforService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * 绯荤粺璁块棶璁板綍
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/monitor/logininfor")
-public class SysLogininforController extends BaseController {
-
-    private final ISysLogininforService logininforService;
-
-    /**
-     * 鑾峰彇绯荤粺璁块棶璁板綍鍒楄〃
-     */
-    @SaCheckPermission("monitor:logininfor:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysLogininfor> list(SysLogininfor logininfor, PageQuery pageQuery) {
-        return logininforService.selectPageLogininforList(logininfor, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭绯荤粺璁块棶璁板綍鍒楄〃
-     */
-    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("monitor:logininfor:export")
-    @PostMapping("/export")
-    public void export(SysLogininfor logininfor, HttpServletResponse response) {
-        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
-        ExcelUtil.exportExcel(list, "鐧诲綍鏃ュ織", SysLogininfor.class, response);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鐧诲綍鏃ュ織
-     * @param infoIds 鏃ュ織ids
-     */
-    @SaCheckPermission("monitor:logininfor:remove")
-    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{infoIds}")
-    public R<Void> remove(@PathVariable Long[] infoIds) {
-        return toAjax(logininforService.deleteLogininforByIds(infoIds));
-    }
-
-    /**
-     * 娓呯悊绯荤粺璁块棶璁板綍
-     */
-    @SaCheckPermission("monitor:logininfor:remove")
-    @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/clean")
-    public R<Void> clean() {
-        logininforService.cleanLogininfor();
-        return R.ok();
-    }
-
-    @SaCheckPermission("monitor:logininfor:unlock")
-    @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
-    @GetMapping("/unlock/{userName}")
-    public R<Void> unlock(@PathVariable("userName") String userName) {
-        String loginName = CacheConstants.PWD_ERR_CNT_KEY + userName;
-        if (RedisUtils.hasKey(loginName)) {
-            RedisUtils.deleteObject(loginName);
-        }
-        return R.ok();
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java
deleted file mode 100644
index 5b72587..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysOperlogController.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.ruoyi.system.controller.monitor;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.domain.SysOperLog;
-import com.ruoyi.system.service.ISysOperLogService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * 鎿嶄綔鏃ュ織璁板綍
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/monitor/operlog")
-public class SysOperlogController extends BaseController {
-
-    private final ISysOperLogService operLogService;
-
-    /**
-     * 鑾峰彇鎿嶄綔鏃ュ織璁板綍鍒楄〃
-     */
-    @SaCheckPermission("monitor:operlog:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysOperLog> list(SysOperLog operLog, PageQuery pageQuery) {
-        return operLogService.selectPageOperLogList(operLog, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭鎿嶄綔鏃ュ織璁板綍鍒楄〃
-     */
-    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("monitor:operlog:export")
-    @PostMapping("/export")
-    public void export(SysOperLog operLog, HttpServletResponse response) {
-        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
-        ExcelUtil.exportExcel(list, "鎿嶄綔鏃ュ織", SysOperLog.class, response);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鎿嶄綔鏃ュ織璁板綍
-     * @param operIds 鏃ュ織ids
-     */
-    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.DELETE)
-    @SaCheckPermission("monitor:operlog:remove")
-    @DeleteMapping("/{operIds}")
-    public R<Void> remove(@PathVariable Long[] operIds) {
-        return toAjax(operLogService.deleteOperLogByIds(operIds));
-    }
-
-    /**
-     * 娓呯悊鎿嶄綔鏃ュ織璁板綍
-     */
-    @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.CLEAN)
-    @SaCheckPermission("monitor:operlog:remove")
-    @DeleteMapping("/clean")
-    public R<Void> clean() {
-        operLogService.cleanOperLog();
-        return R.ok();
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java
deleted file mode 100644
index b1c5e3f..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/monitor/SysUserOnlineController.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.ruoyi.system.controller.monitor;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.dev33.satoken.exception.NotLoginException;
-import cn.dev33.satoken.stp.StpUtil;
-import cn.hutool.core.bean.BeanUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.domain.dto.UserOnlineDTO;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.system.domain.SysUserOnline;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 鍦ㄧ嚎鐢ㄦ埛鐩戞帶
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/monitor/online")
-public class SysUserOnlineController extends BaseController {
-
-    /**
-     * 鑾峰彇鍦ㄧ嚎鐢ㄦ埛鐩戞帶鍒楄〃
-     *
-     * @param ipaddr   IP鍦板潃
-     * @param userName 鐢ㄦ埛鍚�
-     */
-    @SaCheckPermission("monitor:online:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysUserOnline> list(String ipaddr, String userName) {
-        // 鑾峰彇鎵�鏈夋湭杩囨湡鐨� token
-        List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
-        List<UserOnlineDTO> userOnlineDTOList = new ArrayList<>();
-        for (String key : keys) {
-            String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, "");
-            // 濡傛灉宸茬粡杩囨湡鍒欒烦杩�
-            if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < -1) {
-                continue;
-            }
-            userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token));
-        }
-        if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
-            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
-                StringUtils.equals(ipaddr, userOnline.getIpaddr()) &&
-                    StringUtils.equals(userName, userOnline.getUserName())
-            );
-        } else if (StringUtils.isNotEmpty(ipaddr)) {
-            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
-                StringUtils.equals(ipaddr, userOnline.getIpaddr())
-            );
-        } else if (StringUtils.isNotEmpty(userName)) {
-            userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline ->
-                StringUtils.equals(userName, userOnline.getUserName())
-            );
-        }
-        Collections.reverse(userOnlineDTOList);
-        userOnlineDTOList.removeAll(Collections.singleton(null));
-        List<SysUserOnline> userOnlineList = BeanUtil.copyToList(userOnlineDTOList, SysUserOnline.class);
-        return TableDataInfo.build(userOnlineList);
-    }
-
-    /**
-     * 寮洪��鐢ㄦ埛
-     *
-     * @param tokenId token鍊�
-     */
-    @SaCheckPermission("monitor:online:forceLogout")
-    @Log(title = "鍦ㄧ嚎鐢ㄦ埛", businessType = BusinessType.FORCE)
-    @DeleteMapping("/{tokenId}")
-    public R<Void> forceLogout(@PathVariable String tokenId) {
-        try {
-            StpUtil.kickoutByTokenValue(tokenId);
-        } catch (NotLoginException ignored) {
-        }
-        return R.ok();
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java
deleted file mode 100644
index 8959098..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysConfigController.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.domain.SysConfig;
-import com.ruoyi.system.service.ISysConfigService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/config")
-public class SysConfigController extends BaseController {
-
-    private final ISysConfigService configService;
-
-    /**
-     * 鑾峰彇鍙傛暟閰嶇疆鍒楄〃
-     */
-    @SaCheckPermission("system:config:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysConfig> list(SysConfig config, PageQuery pageQuery) {
-        return configService.selectPageConfigList(config, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭鍙傛暟閰嶇疆鍒楄〃
-     */
-    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("system:config:export")
-    @PostMapping("/export")
-    public void export(SysConfig config, HttpServletResponse response) {
-        List<SysConfig> list = configService.selectConfigList(config);
-        ExcelUtil.exportExcel(list, "鍙傛暟鏁版嵁", SysConfig.class, response);
-    }
-
-    /**
-     * 鏍规嵁鍙傛暟缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param configId 鍙傛暟ID
-     */
-    @SaCheckPermission("system:config:query")
-    @GetMapping(value = "/{configId}")
-    public R<SysConfig> getInfo(@PathVariable Long configId) {
-        return R.ok(configService.selectConfigById(configId));
-    }
-
-    /**
-     * 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
-     *
-     * @param configKey 鍙傛暟Key
-     */
-    @GetMapping(value = "/configKey/{configKey}")
-    public R<Void> getConfigKey(@PathVariable String configKey) {
-        return R.ok(configService.selectConfigByKey(configKey));
-    }
-
-    /**
-     * 鏂板鍙傛暟閰嶇疆
-     */
-    @SaCheckPermission("system:config:add")
-    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysConfig config) {
-        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
-            return R.fail("鏂板鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
-        }
-        configService.insertConfig(config);
-        return R.ok();
-    }
-
-    /**
-     * 淇敼鍙傛暟閰嶇疆
-     */
-    @SaCheckPermission("system:config:edit")
-    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysConfig config) {
-        if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) {
-            return R.fail("淇敼鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
-        }
-        configService.updateConfig(config);
-        return R.ok();
-    }
-
-    /**
-     * 鏍规嵁鍙傛暟閿悕淇敼鍙傛暟閰嶇疆
-     */
-    @SaCheckPermission("system:config:edit")
-    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping("/updateByKey")
-    public R<Void> updateByKey(@RequestBody SysConfig config) {
-        configService.updateConfig(config);
-        return R.ok();
-    }
-
-    /**
-     * 鍒犻櫎鍙傛暟閰嶇疆
-     *
-     * @param configIds 鍙傛暟ID涓�
-     */
-    @SaCheckPermission("system:config:remove")
-    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{configIds}")
-    public R<Void> remove(@PathVariable Long[] configIds) {
-        configService.deleteConfigByIds(configIds);
-        return R.ok();
-    }
-
-    /**
-     * 鍒锋柊鍙傛暟缂撳瓨
-     */
-    @SaCheckPermission("system:config:remove")
-    @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/refreshCache")
-    public R<Void> refreshCache() {
-        configService.resetConfigCache();
-        return R.ok();
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java
deleted file mode 100644
index 4334b88..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDeptController.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.util.ArrayUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.service.ISysDeptService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 閮ㄩ棬淇℃伅
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/dept")
-public class SysDeptController extends BaseController {
-
-    private final ISysDeptService deptService;
-
-    /**
-     * 鑾峰彇閮ㄩ棬鍒楄〃
-     */
-    @SaCheckPermission("system:dept:list")
-    @GetMapping("/list")
-    public R<List<SysDept>> list(SysDept dept) {
-        List<SysDept> depts = deptService.selectDeptList(dept);
-        return R.ok(depts);
-    }
-
-    /**
-     * 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
-     *
-     * @param deptId 閮ㄩ棬ID
-     */
-    @SaCheckPermission("system:dept:list")
-    @GetMapping("/list/exclude/{deptId}")
-    public R<List<SysDept>> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) {
-        List<SysDept> depts = deptService.selectDeptList(new SysDept());
-        depts.removeIf(d -> d.getDeptId().equals(deptId)
-            || ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
-        return R.ok(depts);
-    }
-
-    /**
-     * 鏍规嵁閮ㄩ棬缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param deptId 閮ㄩ棬ID
-     */
-    @SaCheckPermission("system:dept:query")
-    @GetMapping(value = "/{deptId}")
-    public R<SysDept> getInfo(@PathVariable Long deptId) {
-        deptService.checkDeptDataScope(deptId);
-        return R.ok(deptService.selectDeptById(deptId));
-    }
-
-    /**
-     * 鏂板閮ㄩ棬
-     */
-    @SaCheckPermission("system:dept:add")
-    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysDept dept) {
-        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
-            return R.fail("鏂板閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
-        }
-        return toAjax(deptService.insertDept(dept));
-    }
-
-    /**
-     * 淇敼閮ㄩ棬
-     */
-    @SaCheckPermission("system:dept:edit")
-    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysDept dept) {
-        Long deptId = dept.getDeptId();
-        deptService.checkDeptDataScope(deptId);
-        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
-            return R.fail("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
-        } else if (dept.getParentId().equals(deptId)) {
-            return R.fail("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛屼笂绾ч儴闂ㄤ笉鑳芥槸鑷繁");
-        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
-            && deptService.selectNormalChildrenDeptById(deptId) > 0) {
-            return R.fail("璇ラ儴闂ㄥ寘鍚湭鍋滅敤鐨勫瓙閮ㄩ棬锛�");
-        }
-        return toAjax(deptService.updateDept(dept));
-    }
-
-    /**
-     * 鍒犻櫎閮ㄩ棬
-     *
-     * @param deptId 閮ㄩ棬ID
-     */
-    @SaCheckPermission("system:dept:remove")
-    @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{deptId}")
-    public R<Void> remove(@PathVariable Long deptId) {
-        if (deptService.hasChildByDeptId(deptId)) {
-            return R.warn("瀛樺湪涓嬬骇閮ㄩ棬,涓嶅厑璁稿垹闄�");
-        }
-        if (deptService.checkDeptExistUser(deptId)) {
-            return R.warn("閮ㄩ棬瀛樺湪鐢ㄦ埛,涓嶅厑璁稿垹闄�");
-        }
-        deptService.checkDeptDataScope(deptId);
-        return toAjax(deptService.deleteDeptById(deptId));
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java
deleted file mode 100644
index 287a1e7..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictDataController.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysDictData;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.service.ISysDictDataService;
-import com.ruoyi.system.service.ISysDictTypeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 鏁版嵁瀛楀吀淇℃伅
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/dict/data")
-public class SysDictDataController extends BaseController {
-
-    private final ISysDictDataService dictDataService;
-    private final ISysDictTypeService dictTypeService;
-
-    /**
-     * 鏌ヨ瀛楀吀鏁版嵁鍒楄〃
-     */
-    @SaCheckPermission("system:dict:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysDictData> list(SysDictData dictData, PageQuery pageQuery) {
-        return dictDataService.selectPageDictDataList(dictData, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭瀛楀吀鏁版嵁鍒楄〃
-     */
-    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("system:dict:export")
-    @PostMapping("/export")
-    public void export(SysDictData dictData, HttpServletResponse response) {
-        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
-        ExcelUtil.exportExcel(list, "瀛楀吀鏁版嵁", SysDictData.class, response);
-    }
-
-    /**
-     * 鏌ヨ瀛楀吀鏁版嵁璇︾粏
-     *
-     * @param dictCode 瀛楀吀code
-     */
-    @SaCheckPermission("system:dict:query")
-    @GetMapping(value = "/{dictCode}")
-    public R<SysDictData> getInfo(@PathVariable Long dictCode) {
-        return R.ok(dictDataService.selectDictDataById(dictCode));
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param dictType 瀛楀吀绫诲瀷
-     */
-    @GetMapping(value = "/type/{dictType}")
-    public R<List<SysDictData>> dictType(@PathVariable String dictType) {
-        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
-        if (ObjectUtil.isNull(data)) {
-            data = new ArrayList<>();
-        }
-        return R.ok(data);
-    }
-
-    /**
-     * 鏂板瀛楀吀绫诲瀷
-     */
-    @SaCheckPermission("system:dict:add")
-    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysDictData dict) {
-        dictDataService.insertDictData(dict);
-        return R.ok();
-    }
-
-    /**
-     * 淇敼淇濆瓨瀛楀吀绫诲瀷
-     */
-    @SaCheckPermission("system:dict:edit")
-    @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysDictData dict) {
-        dictDataService.updateDictData(dict);
-        return R.ok();
-    }
-
-    /**
-     * 鍒犻櫎瀛楀吀绫诲瀷
-     *
-     * @param dictCodes 瀛楀吀code涓�
-     */
-    @SaCheckPermission("system:dict:remove")
-    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{dictCodes}")
-    public R<Void> remove(@PathVariable Long[] dictCodes) {
-        dictDataService.deleteDictDataByIds(dictCodes);
-        return R.ok();
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java
deleted file mode 100644
index 354d2f7..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysDictTypeController.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysDictType;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.service.ISysDictTypeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * 鏁版嵁瀛楀吀淇℃伅
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/dict/type")
-public class SysDictTypeController extends BaseController {
-
-    private final ISysDictTypeService dictTypeService;
-
-    /**
-     * 鏌ヨ瀛楀吀绫诲瀷鍒楄〃
-     */
-    @SaCheckPermission("system:dict:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysDictType> list(SysDictType dictType, PageQuery pageQuery) {
-        return dictTypeService.selectPageDictTypeList(dictType, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭瀛楀吀绫诲瀷鍒楄〃
-     */
-    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("system:dict:export")
-    @PostMapping("/export")
-    public void export(SysDictType dictType, HttpServletResponse response) {
-        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
-        ExcelUtil.exportExcel(list, "瀛楀吀绫诲瀷", SysDictType.class, response);
-    }
-
-    /**
-     * 鏌ヨ瀛楀吀绫诲瀷璇︾粏
-     *
-     * @param dictId 瀛楀吀ID
-     */
-    @SaCheckPermission("system:dict:query")
-    @GetMapping(value = "/{dictId}")
-    public R<SysDictType> getInfo(@PathVariable Long dictId) {
-        return R.ok(dictTypeService.selectDictTypeById(dictId));
-    }
-
-    /**
-     * 鏂板瀛楀吀绫诲瀷
-     */
-    @SaCheckPermission("system:dict:add")
-    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysDictType dict) {
-        if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) {
-            return R.fail("鏂板瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
-        }
-        dictTypeService.insertDictType(dict);
-        return R.ok();
-    }
-
-    /**
-     * 淇敼瀛楀吀绫诲瀷
-     */
-    @SaCheckPermission("system:dict:edit")
-    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysDictType dict) {
-        if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) {
-            return R.fail("淇敼瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
-        }
-        dictTypeService.updateDictType(dict);
-        return R.ok();
-    }
-
-    /**
-     * 鍒犻櫎瀛楀吀绫诲瀷
-     *
-     * @param dictIds 瀛楀吀ID涓�
-     */
-    @SaCheckPermission("system:dict:remove")
-    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{dictIds}")
-    public R<Void> remove(@PathVariable Long[] dictIds) {
-        dictTypeService.deleteDictTypeByIds(dictIds);
-        return R.ok();
-    }
-
-    /**
-     * 鍒锋柊瀛楀吀缂撳瓨
-     */
-    @SaCheckPermission("system:dict:remove")
-    @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
-    @DeleteMapping("/refreshCache")
-    public R<Void> refreshCache() {
-        dictTypeService.resetDictCache();
-        return R.ok();
-    }
-
-    /**
-     * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
-     */
-    @GetMapping("/optionselect")
-    public R<List<SysDictType>> optionselect() {
-        List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
-        return R.ok(dictTypes);
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
deleted file mode 100644
index 6046b0c..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysMenuController.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.lang.tree.Tree;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysMenu;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.service.ISysMenuService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鑿滃崟淇℃伅
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/menu")
-public class SysMenuController extends BaseController {
-
-    private final ISysMenuService menuService;
-
-    /**
-     * 鑾峰彇鑿滃崟鍒楄〃
-     */
-    @SaCheckPermission("system:menu:list")
-    @GetMapping("/list")
-    public R<List<SysMenu>> list(SysMenu menu) {
-        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
-        return R.ok(menus);
-    }
-
-    /**
-     * 鏍规嵁鑿滃崟缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param menuId 鑿滃崟ID
-     */
-    @SaCheckPermission("system:menu:query")
-    @GetMapping(value = "/{menuId}")
-    public R<SysMenu> getInfo(@PathVariable Long menuId) {
-        return R.ok(menuService.selectMenuById(menuId));
-    }
-
-    /**
-     * 鑾峰彇鑿滃崟涓嬫媺鏍戝垪琛�
-     */
-    @GetMapping("/treeselect")
-    public R<List<Tree<Long>>> treeselect(SysMenu menu) {
-        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
-        return R.ok(menuService.buildMenuTreeSelect(menus));
-    }
-
-    /**
-     * 鍔犺浇瀵瑰簲瑙掕壊鑿滃崟鍒楄〃鏍�
-     *
-     * @param roleId 瑙掕壊ID
-     */
-    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
-    public R<Map<String, Object>> roleMenuTreeselect(@PathVariable("roleId") Long roleId) {
-        List<SysMenu> menus = menuService.selectMenuList(getUserId());
-        Map<String, Object> ajax = new HashMap<>();
-        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
-        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
-        return R.ok(ajax);
-    }
-
-    /**
-     * 鏂板鑿滃崟
-     */
-    @SaCheckPermission("system:menu:add")
-    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysMenu menu) {
-        if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
-            return R.fail("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
-        } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
-            return R.fail("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
-        }
-        return toAjax(menuService.insertMenu(menu));
-    }
-
-    /**
-     * 淇敼鑿滃崟
-     */
-    @SaCheckPermission("system:menu:edit")
-    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysMenu menu) {
-        if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) {
-            return R.fail("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
-        } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) {
-            return R.fail("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
-        } else if (menu.getMenuId().equals(menu.getParentId())) {
-            return R.fail("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屼笂绾ц彍鍗曚笉鑳介�夋嫨鑷繁");
-        }
-        return toAjax(menuService.updateMenu(menu));
-    }
-
-    /**
-     * 鍒犻櫎鑿滃崟
-     *
-     * @param menuId 鑿滃崟ID
-     */
-    @SaCheckPermission("system:menu:remove")
-    @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{menuId}")
-    public R<Void> remove(@PathVariable("menuId") Long menuId) {
-        if (menuService.hasChildByMenuId(menuId)) {
-            return R.warn("瀛樺湪瀛愯彍鍗�,涓嶅厑璁稿垹闄�");
-        }
-        if (menuService.checkMenuExistRole(menuId)) {
-            return R.warn("鑿滃崟宸插垎閰�,涓嶅厑璁稿垹闄�");
-        }
-        return toAjax(menuService.deleteMenuById(menuId));
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java
deleted file mode 100644
index ba28194..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysNoticeController.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.system.domain.SysNotice;
-import com.ruoyi.system.service.ISysNoticeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * 鍏憡 淇℃伅鎿嶄綔澶勭悊
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/notice")
-public class SysNoticeController extends BaseController {
-
-    private final ISysNoticeService noticeService;
-
-    /**
-     * 鑾峰彇閫氱煡鍏憡鍒楄〃
-     */
-    @SaCheckPermission("system:notice:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysNotice> list(SysNotice notice, PageQuery pageQuery) {
-        return noticeService.selectPageNoticeList(notice, pageQuery);
-    }
-
-    /**
-     * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param noticeId 鍏憡ID
-     */
-    @SaCheckPermission("system:notice:query")
-    @GetMapping(value = "/{noticeId}")
-    public R<SysNotice> getInfo(@PathVariable Long noticeId) {
-        return R.ok(noticeService.selectNoticeById(noticeId));
-    }
-
-    /**
-     * 鏂板閫氱煡鍏憡
-     */
-    @SaCheckPermission("system:notice:add")
-    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysNotice notice) {
-        return toAjax(noticeService.insertNotice(notice));
-    }
-
-    /**
-     * 淇敼閫氱煡鍏憡
-     */
-    @SaCheckPermission("system:notice:edit")
-    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysNotice notice) {
-        return toAjax(noticeService.updateNotice(notice));
-    }
-
-    /**
-     * 鍒犻櫎閫氱煡鍏憡
-     *
-     * @param noticeIds 鍏憡ID涓�
-     */
-    @SaCheckPermission("system:notice:remove")
-    @Log(title = "閫氱煡鍏憡", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{noticeIds}")
-    public R<Void> remove(@PathVariable Long[] noticeIds) {
-        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java
deleted file mode 100644
index 98f9fdd..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssConfigController.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.annotation.RepeatSubmit;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import com.ruoyi.common.core.validate.QueryGroup;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.system.domain.bo.SysOssConfigBo;
-import com.ruoyi.system.domain.vo.SysOssConfigVo;
-import com.ruoyi.system.service.ISysOssConfigService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.util.Arrays;
-
-/**
- * 瀵硅薄瀛樺偍閰嶇疆
- *
- * @author Lion Li
- * @author 瀛よ垷鐑熼洦
- * @date 2021-08-13
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/oss/config")
-public class SysOssConfigController extends BaseController {
-
-    private final ISysOssConfigService iSysOssConfigService;
-
-    /**
-     * 鏌ヨ瀵硅薄瀛樺偍閰嶇疆鍒楄〃
-     */
-    @SaCheckPermission("system:oss:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
-        return iSysOssConfigService.queryPageList(bo, pageQuery);
-    }
-
-    /**
-     * 鑾峰彇瀵硅薄瀛樺偍閰嶇疆璇︾粏淇℃伅
-     *
-     * @param ossConfigId OSS閰嶇疆ID
-     */
-    @SaCheckPermission("system:oss:query")
-    @GetMapping("/{ossConfigId}")
-    public R<SysOssConfigVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
-                                     @PathVariable Long ossConfigId) {
-        return R.ok(iSysOssConfigService.queryById(ossConfigId));
-    }
-
-    /**
-     * 鏂板瀵硅薄瀛樺偍閰嶇疆
-     */
-    @SaCheckPermission("system:oss:add")
-    @Log(title = "瀵硅薄瀛樺偍閰嶇疆", businessType = BusinessType.INSERT)
-    @RepeatSubmit()
-    @PostMapping()
-    public R<Void> add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) {
-        return toAjax(iSysOssConfigService.insertByBo(bo));
-    }
-
-    /**
-     * 淇敼瀵硅薄瀛樺偍閰嶇疆
-     */
-    @SaCheckPermission("system:oss:edit")
-    @Log(title = "瀵硅薄瀛樺偍閰嶇疆", businessType = BusinessType.UPDATE)
-    @RepeatSubmit()
-    @PutMapping()
-    public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) {
-        return toAjax(iSysOssConfigService.updateByBo(bo));
-    }
-
-    /**
-     * 鍒犻櫎瀵硅薄瀛樺偍閰嶇疆
-     *
-     * @param ossConfigIds OSS閰嶇疆ID涓�
-     */
-    @SaCheckPermission("system:oss:remove")
-    @Log(title = "瀵硅薄瀛樺偍閰嶇疆", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ossConfigIds}")
-    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
-                          @PathVariable Long[] ossConfigIds) {
-        return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true));
-    }
-
-    /**
-     * 鐘舵�佷慨鏀�
-     */
-    @SaCheckPermission("system:oss:edit")
-    @Log(title = "瀵硅薄瀛樺偍鐘舵�佷慨鏀�", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
-    public R<Void> changeStatus(@RequestBody SysOssConfigBo bo) {
-        return toAjax(iSysOssConfigService.updateOssConfigStatus(bo));
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java
deleted file mode 100644
index 893a10d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysOssController.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.http.HttpException;
-import cn.hutool.http.HttpUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.validate.QueryGroup;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.file.FileUtils;
-import com.ruoyi.oss.core.OssClient;
-import com.ruoyi.oss.factory.OssFactory;
-import com.ruoyi.system.domain.SysOss;
-import com.ruoyi.system.domain.bo.SysOssBo;
-import com.ruoyi.system.domain.vo.SysOssVo;
-import com.ruoyi.system.service.ISysOssService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.MediaType;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.constraints.NotEmpty;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鏂囦欢涓婁紶 鎺у埗灞�
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/oss")
-public class SysOssController extends BaseController {
-
-    private final ISysOssService iSysOssService;
-
-    /**
-     * 鏌ヨOSS瀵硅薄瀛樺偍鍒楄〃
-     */
-    @SaCheckPermission("system:oss:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) {
-        return iSysOssService.queryPageList(bo, pageQuery);
-    }
-
-    /**
-     * 鏌ヨOSS瀵硅薄鍩轰簬id涓�
-     *
-     * @param ossIds OSS瀵硅薄ID涓�
-     */
-    @SaCheckPermission("system:oss:list")
-    @GetMapping("/listByIds/{ossIds}")
-    public R<List<SysOssVo>> listByIds(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
-                                       @PathVariable Long[] ossIds) {
-        List<SysOssVo> list = iSysOssService.listByIds(Arrays.asList(ossIds));
-        return R.ok(list);
-    }
-
-    /**
-     * 涓婁紶OSS瀵硅薄瀛樺偍
-     *
-     * @param file 鏂囦欢
-     */
-    @SaCheckPermission("system:oss:upload")
-    @Log(title = "OSS瀵硅薄瀛樺偍", businessType = BusinessType.INSERT)
-    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public R<Map<String, String>> upload(@RequestPart("file") MultipartFile file) {
-        if (ObjectUtil.isNull(file)) {
-            throw new ServiceException("涓婁紶鏂囦欢涓嶈兘涓虹┖");
-        }
-        SysOssVo oss = iSysOssService.upload(file);
-        Map<String, String> map = new HashMap<>(2);
-        map.put("url", oss.getUrl());
-        map.put("fileName", oss.getOriginalName());
-        map.put("ossId", oss.getOssId().toString());
-        return R.ok(map);
-    }
-
-    /**
-     * 涓嬭浇OSS瀵硅薄
-     *
-     * @param ossId OSS瀵硅薄ID
-     */
-    @SaCheckPermission("system:oss:download")
-    @GetMapping("/download/{ossId}")
-    public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
-        iSysOssService.download(ossId,response);
-    }
-
-    /**
-     * 鍒犻櫎OSS瀵硅薄瀛樺偍
-     *
-     * @param ossIds OSS瀵硅薄ID涓�
-     */
-    @SaCheckPermission("system:oss:remove")
-    @Log(title = "OSS瀵硅薄瀛樺偍", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ossIds}")
-    public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
-                          @PathVariable Long[] ossIds) {
-        return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true));
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java
deleted file mode 100644
index b8faaf9..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysPostController.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.domain.SysPost;
-import com.ruoyi.system.service.ISysPostService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * 宀椾綅淇℃伅鎿嶄綔澶勭悊
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/post")
-public class SysPostController extends BaseController {
-
-    private final ISysPostService postService;
-
-    /**
-     * 鑾峰彇宀椾綅鍒楄〃
-     */
-    @SaCheckPermission("system:post:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysPost> list(SysPost post, PageQuery pageQuery) {
-        return postService.selectPagePostList(post, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭宀椾綅鍒楄〃
-     */
-    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("system:post:export")
-    @PostMapping("/export")
-    public void export(SysPost post, HttpServletResponse response) {
-        List<SysPost> list = postService.selectPostList(post);
-        ExcelUtil.exportExcel(list, "宀椾綅鏁版嵁", SysPost.class, response);
-    }
-
-    /**
-     * 鏍规嵁宀椾綅缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param postId 宀椾綅ID
-     */
-    @SaCheckPermission("system:post:query")
-    @GetMapping(value = "/{postId}")
-    public R<SysPost> getInfo(@PathVariable Long postId) {
-        return R.ok(postService.selectPostById(postId));
-    }
-
-    /**
-     * 鏂板宀椾綅
-     */
-    @SaCheckPermission("system:post:add")
-    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysPost post) {
-        if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) {
-            return R.fail("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
-        } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) {
-            return R.fail("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
-        }
-        return toAjax(postService.insertPost(post));
-    }
-
-    /**
-     * 淇敼宀椾綅
-     */
-    @SaCheckPermission("system:post:edit")
-    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysPost post) {
-        if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) {
-            return R.fail("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
-        } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) {
-            return R.fail("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
-        }
-        return toAjax(postService.updatePost(post));
-    }
-
-    /**
-     * 鍒犻櫎宀椾綅
-     *
-     * @param postIds 宀椾綅ID涓�
-     */
-    @SaCheckPermission("system:post:remove")
-    @Log(title = "宀椾綅绠$悊", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{postIds}")
-    public R<Void> remove(@PathVariable Long[] postIds) {
-        return toAjax(postService.deletePostByIds(postIds));
-    }
-
-    /**
-     * 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
-     */
-    @GetMapping("/optionselect")
-    public R<List<SysPost>> optionselect() {
-        List<SysPost> posts = postService.selectPostAll();
-        return R.ok(posts);
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java
deleted file mode 100644
index a777410..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysProfileController.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.secure.BCrypt;
-import cn.hutool.core.io.FileUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.MimeTypeUtils;
-import com.ruoyi.system.domain.vo.SysOssVo;
-import com.ruoyi.system.service.ISysOssService;
-import com.ruoyi.system.service.ISysUserService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.MediaType;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 涓汉淇℃伅 涓氬姟澶勭悊
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/user/profile")
-public class SysProfileController extends BaseController {
-
-    private final ISysUserService userService;
-    private final ISysOssService iSysOssService;
-
-    /**
-     * 涓汉淇℃伅
-     */
-    @GetMapping
-    public R<Map<String, Object>> profile() {
-        SysUser user = userService.selectUserById(getUserId());
-        Map<String, Object> ajax = new HashMap<>();
-        ajax.put("user", user);
-        ajax.put("roleGroup", userService.selectUserRoleGroup(user.getUserName()));
-        ajax.put("postGroup", userService.selectUserPostGroup(user.getUserName()));
-        return R.ok(ajax);
-    }
-
-    /**
-     * 淇敼鐢ㄦ埛
-     */
-    @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> updateProfile(@RequestBody SysUser user) {
-        if (StringUtils.isNotEmpty(user.getPhonenumber())
-            && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
-            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
-        }
-        if (StringUtils.isNotEmpty(user.getEmail())
-            && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
-            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
-        }
-        user.setUserId(getUserId());
-        user.setUserName(null);
-        user.setPassword(null);
-        user.setAvatar(null);
-        user.setDeptId(null);
-        if (userService.updateUserProfile(user) > 0) {
-            return R.ok();
-        }
-        return R.fail("淇敼涓汉淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
-    }
-
-    /**
-     * 閲嶇疆瀵嗙爜
-     *
-     * @param newPassword 鏃у瘑鐮�
-     * @param oldPassword 鏂板瘑鐮�
-     */
-    @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
-    @PutMapping("/updatePwd")
-    public R<Void> updatePwd(String oldPassword, String newPassword) {
-        SysUser user = userService.selectUserById(LoginHelper.getUserId());
-        String userName = user.getUserName();
-        String password = user.getPassword();
-        if (!BCrypt.checkpw(oldPassword, password)) {
-            return R.fail("淇敼瀵嗙爜澶辫触锛屾棫瀵嗙爜閿欒");
-        }
-        if (BCrypt.checkpw(newPassword, password)) {
-            return R.fail("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�");
-        }
-
-        if (userService.resetUserPwd(userName, BCrypt.hashpw(newPassword)) > 0) {
-            return R.ok();
-        }
-        return R.fail("淇敼瀵嗙爜寮傚父锛岃鑱旂郴绠$悊鍛�");
-    }
-
-    /**
-     * 澶村儚涓婁紶
-     *
-     * @param avatarfile 鐢ㄦ埛澶村儚
-     */
-    @Log(title = "鐢ㄦ埛澶村儚", businessType = BusinessType.UPDATE)
-    @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public R<Map<String, Object>> avatar(@RequestPart("avatarfile") MultipartFile avatarfile) {
-        Map<String, Object> ajax = new HashMap<>();
-        if (!avatarfile.isEmpty()) {
-            String extension = FileUtil.extName(avatarfile.getOriginalFilename());
-            if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
-                return R.fail("鏂囦欢鏍煎紡涓嶆纭紝璇蜂笂浼�" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "鏍煎紡");
-            }
-            SysOssVo oss = iSysOssService.upload(avatarfile);
-            String avatar = oss.getUrl();
-            if (userService.updateUserAvatar(getUsername(), avatar)) {
-                ajax.put("imgUrl", avatar);
-                return R.ok(ajax);
-            }
-        }
-        return R.fail("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛�");
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java
deleted file mode 100644
index 0bc73cb..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysRoleController.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.domain.SysUserRole;
-import com.ruoyi.system.service.ISysDeptService;
-import com.ruoyi.system.service.ISysRoleService;
-import com.ruoyi.system.service.ISysUserService;
-import com.ruoyi.system.service.SysPermissionService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 瑙掕壊淇℃伅
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/role")
-public class SysRoleController extends BaseController {
-
-    private final ISysRoleService roleService;
-    private final ISysUserService userService;
-    private final ISysDeptService deptService;
-    private final SysPermissionService permissionService;
-
-    /**
-     * 鑾峰彇瑙掕壊淇℃伅鍒楄〃
-     */
-    @SaCheckPermission("system:role:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysRole> list(SysRole role, PageQuery pageQuery) {
-        return roleService.selectPageRoleList(role, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭瑙掕壊淇℃伅鍒楄〃
-     */
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("system:role:export")
-    @PostMapping("/export")
-    public void export(SysRole role, HttpServletResponse response) {
-        List<SysRole> list = roleService.selectRoleList(role);
-        ExcelUtil.exportExcel(list, "瑙掕壊鏁版嵁", SysRole.class, response);
-    }
-
-    /**
-     * 鏍规嵁瑙掕壊缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param roleId 瑙掕壊ID
-     */
-    @SaCheckPermission("system:role:query")
-    @GetMapping(value = "/{roleId}")
-    public R<SysRole> getInfo(@PathVariable Long roleId) {
-        roleService.checkRoleDataScope(roleId);
-        return R.ok(roleService.selectRoleById(roleId));
-    }
-
-    /**
-     * 鏂板瑙掕壊
-     */
-    @SaCheckPermission("system:role:add")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysRole role) {
-        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
-            return R.fail("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
-        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
-            return R.fail("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
-        }
-        return toAjax(roleService.insertRole(role));
-
-    }
-
-    /**
-     * 淇敼淇濆瓨瑙掕壊
-     */
-    @SaCheckPermission("system:role:edit")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysRole role) {
-        roleService.checkRoleAllowed(role);
-        roleService.checkRoleDataScope(role.getRoleId());
-        if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
-            return R.fail("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
-        } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
-            return R.fail("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
-        }
-
-        if (roleService.updateRole(role) > 0) {
-            // 鏇存柊缂撳瓨鐢ㄦ埛鏉冮檺
-            LoginUser loginUser = getLoginUser();
-            SysUser sysUser = userService.selectUserById(loginUser.getUserId());
-            if (ObjectUtil.isNotNull(sysUser) && !sysUser.isAdmin()) {
-                loginUser.setMenuPermission(permissionService.getMenuPermission(sysUser));
-                LoginHelper.setLoginUser(loginUser);
-            }
-            return R.ok();
-        }
-        return R.fail("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑱旂郴绠$悊鍛�");
-    }
-
-    /**
-     * 淇敼淇濆瓨鏁版嵁鏉冮檺
-     */
-    @SaCheckPermission("system:role:edit")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping("/dataScope")
-    public R<Void> dataScope(@RequestBody SysRole role) {
-        roleService.checkRoleAllowed(role);
-        roleService.checkRoleDataScope(role.getRoleId());
-        return toAjax(roleService.authDataScope(role));
-    }
-
-    /**
-     * 鐘舵�佷慨鏀�
-     */
-    @SaCheckPermission("system:role:edit")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
-    public R<Void> changeStatus(@RequestBody SysRole role) {
-        roleService.checkRoleAllowed(role);
-        roleService.checkRoleDataScope(role.getRoleId());
-        return toAjax(roleService.updateRoleStatus(role));
-    }
-
-    /**
-     * 鍒犻櫎瑙掕壊
-     *
-     * @param roleIds 瑙掕壊ID涓�
-     */
-    @SaCheckPermission("system:role:remove")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{roleIds}")
-    public R<Void> remove(@PathVariable Long[] roleIds) {
-        return toAjax(roleService.deleteRoleByIds(roleIds));
-    }
-
-    /**
-     * 鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
-     */
-    @SaCheckPermission("system:role:query")
-    @GetMapping("/optionselect")
-    public R<List<SysRole>> optionselect() {
-        return R.ok(roleService.selectRoleAll());
-    }
-
-    /**
-     * 鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
-     */
-    @SaCheckPermission("system:role:list")
-    @GetMapping("/authUser/allocatedList")
-    public TableDataInfo<SysUser> allocatedList(SysUser user, PageQuery pageQuery) {
-        return userService.selectAllocatedList(user, pageQuery);
-    }
-
-    /**
-     * 鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
-     */
-    @SaCheckPermission("system:role:list")
-    @GetMapping("/authUser/unallocatedList")
-    public TableDataInfo<SysUser> unallocatedList(SysUser user, PageQuery pageQuery) {
-        return userService.selectUnallocatedList(user, pageQuery);
-    }
-
-    /**
-     * 鍙栨秷鎺堟潈鐢ㄦ埛
-     */
-    @SaCheckPermission("system:role:edit")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
-    @PutMapping("/authUser/cancel")
-    public R<Void> cancelAuthUser(@RequestBody SysUserRole userRole) {
-        return toAjax(roleService.deleteAuthUser(userRole));
-    }
-
-    /**
-     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛
-     *
-     * @param roleId  瑙掕壊ID
-     * @param userIds 鐢ㄦ埛ID涓�
-     */
-    @SaCheckPermission("system:role:edit")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
-    @PutMapping("/authUser/cancelAll")
-    public R<Void> cancelAuthUserAll(Long roleId, Long[] userIds) {
-        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
-    }
-
-    /**
-     * 鎵归噺閫夋嫨鐢ㄦ埛鎺堟潈
-     *
-     * @param roleId  瑙掕壊ID
-     * @param userIds 鐢ㄦ埛ID涓�
-     */
-    @SaCheckPermission("system:role:edit")
-    @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
-    @PutMapping("/authUser/selectAll")
-    public R<Void> selectAuthUserAll(Long roleId, Long[] userIds) {
-        roleService.checkRoleDataScope(roleId);
-        return toAjax(roleService.insertAuthUsers(roleId, userIds));
-    }
-
-    /**
-     * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
-     *
-     * @param roleId 瑙掕壊ID
-     */
-    @SaCheckPermission("system:role:list")
-    @GetMapping(value = "/deptTree/{roleId}")
-    public R<Map<String, Object>> roleDeptTreeselect(@PathVariable("roleId") Long roleId) {
-        Map<String, Object> ajax = new HashMap<>();
-        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
-        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
-        return R.ok(ajax);
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
deleted file mode 100644
index 657a802..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysUserController.java
+++ /dev/null
@@ -1,253 +0,0 @@
-package com.ruoyi.system.controller.system;
-
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.dev33.satoken.secure.BCrypt;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.lang.tree.Tree;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.R;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.excel.ExcelResult;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.system.domain.vo.SysUserExportVo;
-import com.ruoyi.system.domain.vo.SysUserImportVo;
-import com.ruoyi.system.listener.SysUserImportListener;
-import com.ruoyi.system.service.ISysDeptService;
-import com.ruoyi.system.service.ISysPostService;
-import com.ruoyi.system.service.ISysRoleService;
-import com.ruoyi.system.service.ISysUserService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.MediaType;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鐢ㄦ埛淇℃伅
- *
- * @author Lion Li
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/system/user")
-public class SysUserController extends BaseController {
-
-    private final ISysUserService userService;
-    private final ISysRoleService roleService;
-    private final ISysPostService postService;
-    private final ISysDeptService deptService;
-
-    /**
-     * 鑾峰彇鐢ㄦ埛鍒楄〃
-     */
-    @SaCheckPermission("system:user:list")
-    @GetMapping("/list")
-    public TableDataInfo<SysUser> list(SysUser user, PageQuery pageQuery) {
-        return userService.selectPageUserList(user, pageQuery);
-    }
-
-    /**
-     * 瀵煎嚭鐢ㄦ埛鍒楄〃
-     */
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.EXPORT)
-    @SaCheckPermission("system:user:export")
-    @PostMapping("/export")
-    public void export(SysUser user, HttpServletResponse response) {
-        List<SysUser> list = userService.selectUserList(user);
-        List<SysUserExportVo> listVo = BeanUtil.copyToList(list, SysUserExportVo.class);
-        for (int i = 0; i < list.size(); i++) {
-            SysDept dept = list.get(i).getDept();
-            SysUserExportVo vo = listVo.get(i);
-            if (ObjectUtil.isNotEmpty(dept)) {
-                vo.setDeptName(dept.getDeptName());
-                vo.setLeader(dept.getLeader());
-            }
-        }
-        ExcelUtil.exportExcel(listVo, "鐢ㄦ埛鏁版嵁", SysUserExportVo.class, response);
-    }
-
-    /**
-     * 瀵煎叆鏁版嵁
-     *
-     * @param file          瀵煎叆鏂囦欢
-     * @param updateSupport 鏄惁鏇存柊宸插瓨鍦ㄦ暟鎹�
-     */
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.IMPORT)
-    @SaCheckPermission("system:user:import")
-    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
-        ExcelResult<SysUserImportVo> result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport));
-        return R.ok(result.getAnalysis());
-    }
-
-    /**
-     * 鑾峰彇瀵煎叆妯℃澘
-     */
-    @PostMapping("/importTemplate")
-    public void importTemplate(HttpServletResponse response) {
-        ExcelUtil.exportExcel(new ArrayList<>(), "鐢ㄦ埛鏁版嵁", SysUserImportVo.class, response);
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇璇︾粏淇℃伅
-     *
-     * @param userId 鐢ㄦ埛ID
-     */
-    @SaCheckPermission("system:user:query")
-    @GetMapping(value = {"/", "/{userId}"})
-    public R<Map<String, Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId) {
-        userService.checkUserDataScope(userId);
-        Map<String, Object> ajax = new HashMap<>();
-        List<SysRole> roles = roleService.selectRoleAll();
-        ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
-        ajax.put("posts", postService.selectPostAll());
-        if (ObjectUtil.isNotNull(userId)) {
-            SysUser sysUser = userService.selectUserById(userId);
-            ajax.put("user", sysUser);
-            ajax.put("postIds", postService.selectPostListByUserId(userId));
-            ajax.put("roleIds", StreamUtils.toList(sysUser.getRoles(), SysRole::getRoleId));
-        }
-        return R.ok(ajax);
-    }
-
-    /**
-     * 鏂板鐢ㄦ埛
-     */
-    @SaCheckPermission("system:user:add")
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R<Void> add(@Validated @RequestBody SysUser user) {
-        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) {
-            return R.fail("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
-        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
-            && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
-            return R.fail("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
-        } else if (StringUtils.isNotEmpty(user.getEmail())
-            && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
-            return R.fail("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
-        }
-        user.setPassword(BCrypt.hashpw(user.getPassword()));
-        return toAjax(userService.insertUser(user));
-    }
-
-    /**
-     * 淇敼鐢ㄦ埛
-     */
-    @SaCheckPermission("system:user:edit")
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R<Void> edit(@Validated @RequestBody SysUser user) {
-        userService.checkUserAllowed(user);
-        userService.checkUserDataScope(user.getUserId());
-        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) {
-            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
-        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
-            && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
-            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
-        } else if (StringUtils.isNotEmpty(user.getEmail())
-            && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
-            return R.fail("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
-        }
-        return toAjax(userService.updateUser(user));
-    }
-
-    /**
-     * 鍒犻櫎鐢ㄦ埛
-     *
-     * @param userIds 瑙掕壊ID涓�
-     */
-    @SaCheckPermission("system:user:remove")
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{userIds}")
-    public R<Void> remove(@PathVariable Long[] userIds) {
-        if (ArrayUtil.contains(userIds, getUserId())) {
-            return R.fail("褰撳墠鐢ㄦ埛涓嶈兘鍒犻櫎");
-        }
-        return toAjax(userService.deleteUserByIds(userIds));
-    }
-
-    /**
-     * 閲嶇疆瀵嗙爜
-     */
-    @SaCheckPermission("system:user:resetPwd")
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping("/resetPwd")
-    public R<Void> resetPwd(@RequestBody SysUser user) {
-        userService.checkUserAllowed(user);
-        userService.checkUserDataScope(user.getUserId());
-        user.setPassword(BCrypt.hashpw(user.getPassword()));
-        return toAjax(userService.resetPwd(user));
-    }
-
-    /**
-     * 鐘舵�佷慨鏀�
-     */
-    @SaCheckPermission("system:user:edit")
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
-    public R<Void> changeStatus(@RequestBody SysUser user) {
-        userService.checkUserAllowed(user);
-        userService.checkUserDataScope(user.getUserId());
-        return toAjax(userService.updateUserStatus(user));
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇鎺堟潈瑙掕壊
-     *
-     * @param userId 鐢ㄦ埛ID
-     */
-    @SaCheckPermission("system:user:query")
-    @GetMapping("/authRole/{userId}")
-    public R<Map<String, Object>> authRole(@PathVariable Long userId) {
-        SysUser user = userService.selectUserById(userId);
-        List<SysRole> roles = roleService.selectRolesByUserId(userId);
-        Map<String, Object> ajax = new HashMap<>();
-        ajax.put("user", user);
-        ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
-        return R.ok(ajax);
-    }
-
-    /**
-     * 鐢ㄦ埛鎺堟潈瑙掕壊
-     *
-     * @param userId  鐢ㄦ埛Id
-     * @param roleIds 瑙掕壊ID涓�
-     */
-    @SaCheckPermission("system:user:edit")
-    @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.GRANT)
-    @PutMapping("/authRole")
-    public R<Void> insertAuthRole(Long userId, Long[] roleIds) {
-        userService.checkUserDataScope(userId);
-        userService.insertUserAuth(userId, roleIds);
-        return R.ok();
-    }
-
-    /**
-     * 鑾峰彇閮ㄩ棬鏍戝垪琛�
-     */
-    @SaCheckPermission("system:user:list")
-    @GetMapping("/deptTree")
-    public R<List<Tree<Long>>> deptTree(SysDept dept) {
-        return R.ok(deptService.selectDeptTreeList(dept));
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java
deleted file mode 100644
index 974019d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.ruoyi.common.utils.StringUtils;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * 缂撳瓨淇℃伅
- *
- * @author Lion Li
- */
-@Data
-@NoArgsConstructor
-public class SysCache {
-
-    /**
-     * 缂撳瓨鍚嶇О
-     */
-    private String cacheName = "";
-
-    /**
-     * 缂撳瓨閿悕
-     */
-    private String cacheKey = "";
-
-    /**
-     * 缂撳瓨鍐呭
-     */
-    private String cacheValue = "";
-
-    /**
-     * 澶囨敞
-     */
-    private String remark = "";
-
-    public SysCache(String cacheName, String remark) {
-        this.cacheName = cacheName;
-        this.remark = remark;
-    }
-
-    public SysCache(String cacheName, String cacheKey, String cacheValue) {
-        this.cacheName = StringUtils.replace(cacheName, ":", "");
-        this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
-        this.cacheValue = cacheValue;
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
deleted file mode 100644
index ab33482..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-
-/**
- * 鍙傛暟閰嶇疆琛� sys_config
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_config")
-@ExcelIgnoreUnannotated
-public class SysConfig extends BaseEntity {
-
-    /**
-     * 鍙傛暟涓婚敭
-     */
-    @ExcelProperty(value = "鍙傛暟涓婚敭")
-    @TableId(value = "config_id")
-    private Long configId;
-
-    /**
-     * 鍙傛暟鍚嶇О
-     */
-    @ExcelProperty(value = "鍙傛暟鍚嶇О")
-    @NotBlank(message = "鍙傛暟鍚嶇О涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "鍙傛暟鍚嶇О涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String configName;
-
-    /**
-     * 鍙傛暟閿悕
-     */
-    @ExcelProperty(value = "鍙傛暟閿悕")
-    @NotBlank(message = "鍙傛暟閿悕闀垮害涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "鍙傛暟閿悕闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String configKey;
-
-    /**
-     * 鍙傛暟閿��
-     */
-    @ExcelProperty(value = "鍙傛暟閿��")
-    @NotBlank(message = "鍙傛暟閿�间笉鑳戒负绌�")
-    @Size(min = 0, max = 500, message = "鍙傛暟閿�奸暱搴︿笉鑳借秴杩噞max}涓瓧绗�")
-    private String configValue;
-
-    /**
-     * 绯荤粺鍐呯疆锛圷鏄� N鍚︼級
-     */
-    @ExcelProperty(value = "绯荤粺鍐呯疆", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_yes_no")
-    private String configType;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
deleted file mode 100644
index b0fcdbc..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDept.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.core.domain.TreeEntity;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import java.io.Serial;
-
-/**
- * 閮ㄩ棬琛� sys_dept
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_dept")
-public class SysDept extends TreeEntity<SysDept> {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 閮ㄩ棬ID
-     */
-    @TableId(value = "dept_id")
-    private Long deptId;
-
-    /**
-     * 閮ㄩ棬鍚嶇О
-     */
-    @NotBlank(message = "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖")
-    @Size(min = 0, max = 30, message = "閮ㄩ棬鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String deptName;
-
-    /**
-     * 鏄剧ず椤哄簭
-     */
-    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
-    private Integer orderNum;
-
-    /**
-     * 璐熻矗浜�
-     */
-    private String leader;
-
-    /**
-     * 鑱旂郴鐢佃瘽
-     */
-    @Size(min = 0, max = 11, message = "鑱旂郴鐢佃瘽闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String phone;
-
-    /**
-     * 閭
-     */
-    @Email(message = "閭鏍煎紡涓嶆纭�")
-    @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String email;
-
-    /**
-     * 閮ㄩ棬鐘舵��:0姝e父,1鍋滅敤
-     */
-    private String status;
-
-    /**
-     * 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�
-     */
-    @TableLogic
-    private String delFlag;
-
-    /**
-     * 绁栫骇鍒楄〃
-     */
-    private String ancestors;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java
deleted file mode 100644
index 02d114d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictData.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-
-/**
- * 瀛楀吀鏁版嵁琛� sys_dict_data
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_dict_data")
-@ExcelIgnoreUnannotated
-public class SysDictData extends BaseEntity {
-
-    /**
-     * 瀛楀吀缂栫爜
-     */
-    @ExcelProperty(value = "瀛楀吀缂栫爜")
-    @TableId(value = "dict_code")
-    private Long dictCode;
-
-    /**
-     * 瀛楀吀鎺掑簭
-     */
-    @ExcelProperty(value = "瀛楀吀鎺掑簭")
-    private Integer dictSort;
-
-    /**
-     * 瀛楀吀鏍囩
-     */
-    @ExcelProperty(value = "瀛楀吀鏍囩")
-    @NotBlank(message = "瀛楀吀鏍囩涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "瀛楀吀鏍囩闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String dictLabel;
-
-    /**
-     * 瀛楀吀閿��
-     */
-    @ExcelProperty(value = "瀛楀吀閿��")
-    @NotBlank(message = "瀛楀吀閿�间笉鑳戒负绌�")
-    @Size(min = 0, max = 100, message = "瀛楀吀閿�奸暱搴︿笉鑳借秴杩噞max}涓瓧绗�")
-    private String dictValue;
-
-    /**
-     * 瀛楀吀绫诲瀷
-     */
-    @ExcelProperty(value = "瀛楀吀绫诲瀷")
-    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String dictType;
-
-    /**
-     * 鏍峰紡灞炴�э紙鍏朵粬鏍峰紡鎵╁睍锛�
-     */
-    @Size(min = 0, max = 100, message = "鏍峰紡灞炴�ч暱搴︿笉鑳借秴杩噞max}涓瓧绗�")
-    private String cssClass;
-
-    /**
-     * 琛ㄦ牸瀛楀吀鏍峰紡
-     */
-    private String listClass;
-
-    /**
-     * 鏄惁榛樿锛圷鏄� N鍚︼級
-     */
-    @ExcelProperty(value = "鏄惁榛樿", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_yes_no")
-    private String isDefault;
-
-    /**
-     * 鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_normal_disable")
-    private String status;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    public boolean getDefault() {
-        return UserConstants.YES.equals(this.isDefault);
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java
deleted file mode 100644
index 54e3a2b..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysDictType.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-
-/**
- * 瀛楀吀绫诲瀷琛� sys_dict_type
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_dict_type")
-@ExcelIgnoreUnannotated
-public class SysDictType extends BaseEntity {
-
-    /**
-     * 瀛楀吀涓婚敭
-     */
-    @ExcelProperty(value = "瀛楀吀涓婚敭")
-    @TableId(value = "dict_id")
-    private Long dictId;
-
-    /**
-     * 瀛楀吀鍚嶇О
-     */
-    @ExcelProperty(value = "瀛楀吀鍚嶇О")
-    @NotBlank(message = "瀛楀吀鍚嶇О涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String dictName;
-
-    /**
-     * 瀛楀吀绫诲瀷
-     */
-    @ExcelProperty(value = "瀛楀吀绫诲瀷")
-    @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷绫诲瀷闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "瀛楀吀绫诲瀷蹇呴』浠ュ瓧姣嶅紑澶达紝涓斿彧鑳戒负锛堝皬鍐欏瓧姣嶏紝鏁板瓧锛屼笅婊戠嚎锛�")
-    private String dictType;
-
-    /**
-     * 鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_normal_disable")
-    private String status;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
deleted file mode 100644
index 896890a..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import lombok.Data;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 绯荤粺璁块棶璁板綍琛� sys_logininfor
- *
- * @author Lion Li
- */
-
-@Data
-@TableName("sys_logininfor")
-@ExcelIgnoreUnannotated
-public class SysLogininfor implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * ID
-     */
-    @ExcelProperty(value = "搴忓彿")
-    @TableId(value = "info_id")
-    private Long infoId;
-
-    /**
-     * 鐢ㄦ埛璐﹀彿
-     */
-    @ExcelProperty(value = "鐢ㄦ埛璐﹀彿")
-    private String userName;
-
-    /**
-     * 鐧诲綍鐘舵�� 0鎴愬姛 1澶辫触
-     */
-    @ExcelProperty(value = "鐧诲綍鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_common_status")
-    private String status;
-
-    /**
-     * 鐧诲綍IP鍦板潃
-     */
-    @ExcelProperty(value = "鐧诲綍鍦板潃")
-    private String ipaddr;
-
-    /**
-     * 鐧诲綍鍦扮偣
-     */
-    @ExcelProperty(value = "鐧诲綍鍦扮偣")
-    private String loginLocation;
-
-    /**
-     * 娴忚鍣ㄧ被鍨�
-     */
-    @ExcelProperty(value = "娴忚鍣�")
-    private String browser;
-
-    /**
-     * 鎿嶄綔绯荤粺
-     */
-    @ExcelProperty(value = "鎿嶄綔绯荤粺")
-    private String os;
-
-    /**
-     * 鎻愮ず娑堟伅
-     */
-    @ExcelProperty(value = "鎻愮ず娑堟伅")
-    private String msg;
-
-    /**
-     * 璁块棶鏃堕棿
-     */
-    @ExcelProperty(value = "璁块棶鏃堕棿")
-    private Date loginTime;
-
-    /**
-     * 璇锋眰鍙傛暟
-     */
-    @TableField(exist = false)
-    private Map<String, Object> params = new HashMap<>();
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
deleted file mode 100644
index 8eb99d1..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysMenu.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.ruoyi.common.core.domain.TreeEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-
-/**
- * 鑿滃崟鏉冮檺琛� sys_menu
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_menu")
-public class SysMenu extends TreeEntity<SysMenu> {
-
-    /**
-     * 鑿滃崟ID
-     */
-    @TableId(value = "menu_id")
-    private Long menuId;
-
-    /**
-     * 鑿滃崟鍚嶇О
-     */
-    @NotBlank(message = "鑿滃崟鍚嶇О涓嶈兘涓虹┖")
-    @Size(min = 0, max = 50, message = "鑿滃崟鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String menuName;
-
-    /**
-     * 鏄剧ず椤哄簭
-     */
-    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
-    private Integer orderNum;
-
-    /**
-     * 璺敱鍦板潃
-     */
-    @Size(min = 0, max = 200, message = "璺敱鍦板潃涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String path;
-
-    /**
-     * 缁勪欢璺緞
-     */
-    @Size(min = 0, max = 200, message = "缁勪欢璺緞涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String component;
-
-    /**
-     * 璺敱鍙傛暟
-     */
-    private String queryParam;
-
-    /**
-     * 鏄惁涓哄閾撅紙0鏄� 1鍚︼級
-     */
-    private String isFrame;
-
-    /**
-     * 鏄惁缂撳瓨锛�0缂撳瓨 1涓嶇紦瀛橈級
-     */
-    private String isCache;
-
-    /**
-     * 绫诲瀷锛圡鐩綍 C鑿滃崟 F鎸夐挳锛�
-     */
-    @NotBlank(message = "鑿滃崟绫诲瀷涓嶈兘涓虹┖")
-    private String menuType;
-
-    /**
-     * 鏄剧ず鐘舵�侊紙0鏄剧ず 1闅愯棌锛�
-     */
-    private String visible;
-
-    /**
-     * 鑿滃崟鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    private String status;
-
-    /**
-     * 鏉冮檺瀛楃涓�
-     */
-    @JsonInclude(JsonInclude.Include.NON_NULL)
-    @Size(min = 0, max = 100, message = "鏉冮檺鏍囪瘑闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String perms;
-
-    /**
-     * 鑿滃崟鍥炬爣
-     */
-    private String icon;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
deleted file mode 100644
index b5fe961..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.xss.Xss;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-
-
-/**
- * 閫氱煡鍏憡琛� sys_notice
- *
- * @author Lion Li
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_notice")
-public class SysNotice extends BaseEntity {
-
-    /**
-     * 鍏憡ID
-     */
-    @TableId(value = "notice_id")
-    private Long noticeId;
-
-    /**
-     * 鍏憡鏍囬
-     */
-    @Xss(message = "鍏憡鏍囬涓嶈兘鍖呭惈鑴氭湰瀛楃")
-    @NotBlank(message = "鍏憡鏍囬涓嶈兘涓虹┖")
-    @Size(min = 0, max = 50, message = "鍏憡鏍囬涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String noticeTitle;
-
-    /**
-     * 鍏憡绫诲瀷锛�1閫氱煡 2鍏憡锛�
-     */
-    private String noticeType;
-
-    /**
-     * 鍏憡鍐呭
-     */
-    private String noticeContent;
-
-    /**
-     * 鍏憡鐘舵�侊紙0姝e父 1鍏抽棴锛�
-     */
-    private String status;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
deleted file mode 100644
index 9f9ca51..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import lombok.Data;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 鎿嶄綔鏃ュ織璁板綍琛� oper_log
- *
- * @author Lion Li
- */
-
-@Data
-@TableName("sys_oper_log")
-@ExcelIgnoreUnannotated
-public class SysOperLog implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鏃ュ織涓婚敭
-     */
-    @ExcelProperty(value = "鏃ュ織涓婚敭")
-    @TableId(value = "oper_id")
-    private Long operId;
-
-    /**
-     * 鎿嶄綔妯″潡
-     */
-    @ExcelProperty(value = "鎿嶄綔妯″潡")
-    private String title;
-
-    /**
-     * 涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛�
-     */
-    @ExcelProperty(value = "涓氬姟绫诲瀷", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_oper_type")
-    private Integer businessType;
-
-    /**
-     * 涓氬姟绫诲瀷鏁扮粍
-     */
-    @TableField(exist = false)
-    private Integer[] businessTypes;
-
-    /**
-     * 璇锋眰鏂规硶
-     */
-    @ExcelProperty(value = "璇锋眰鏂规硶")
-    private String method;
-
-    /**
-     * 璇锋眰鏂瑰紡
-     */
-    @ExcelProperty(value = "璇锋眰鏂瑰紡")
-    private String requestMethod;
-
-    /**
-     * 鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級
-     */
-    @ExcelProperty(value = "鎿嶄綔绫诲埆", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "0=鍏跺畠,1=鍚庡彴鐢ㄦ埛,2=鎵嬫満绔敤鎴�")
-    private Integer operatorType;
-
-    /**
-     * 鎿嶄綔浜哄憳
-     */
-    @ExcelProperty(value = "鎿嶄綔浜哄憳")
-    private String operName;
-
-    /**
-     * 閮ㄩ棬鍚嶇О
-     */
-    @ExcelProperty(value = "閮ㄩ棬鍚嶇О")
-    private String deptName;
-
-    /**
-     * 璇锋眰url
-     */
-    @ExcelProperty(value = "璇锋眰鍦板潃")
-    private String operUrl;
-
-    /**
-     * 鎿嶄綔鍦板潃
-     */
-    @ExcelProperty(value = "鎿嶄綔鍦板潃")
-    private String operIp;
-
-    /**
-     * 鎿嶄綔鍦扮偣
-     */
-    @ExcelProperty(value = "鎿嶄綔鍦扮偣")
-    private String operLocation;
-
-    /**
-     * 璇锋眰鍙傛暟
-     */
-    @ExcelProperty(value = "璇锋眰鍙傛暟")
-    private String operParam;
-
-    /**
-     * 杩斿洖鍙傛暟
-     */
-    @ExcelProperty(value = "杩斿洖鍙傛暟")
-    private String jsonResult;
-
-    /**
-     * 鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛�
-     */
-    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_common_status")
-    private Integer status;
-
-    /**
-     * 閿欒娑堟伅
-     */
-    @ExcelProperty(value = "閿欒娑堟伅")
-    private String errorMsg;
-
-    /**
-     * 鎿嶄綔鏃堕棿
-     */
-    @ExcelProperty(value = "鎿嶄綔鏃堕棿")
-    private Date operTime;
-
-    /**
-     * 璇锋眰鍙傛暟
-     */
-    @TableField(exist = false)
-    private Map<String, Object> params = new HashMap<>();
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java
deleted file mode 100644
index 968304b..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOss.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * OSS瀵硅薄瀛樺偍瀵硅薄
- *
- * @author Lion Li
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_oss")
-public class SysOss extends BaseEntity {
-
-    /**
-     * 瀵硅薄瀛樺偍涓婚敭
-     */
-    @TableId(value = "oss_id")
-    private Long ossId;
-
-    /**
-     * 鏂囦欢鍚�
-     */
-    private String fileName;
-
-    /**
-     * 鍘熷悕
-     */
-    private String originalName;
-
-    /**
-     * 鏂囦欢鍚庣紑鍚�
-     */
-    private String fileSuffix;
-
-    /**
-     * URL鍦板潃
-     */
-    private String url;
-
-    /**
-     * 鏈嶅姟鍟�
-     */
-    private String service;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
deleted file mode 100644
index ac5e5a3..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 瀵硅薄瀛樺偍閰嶇疆瀵硅薄 sys_oss_config
- *
- * @author Lion Li
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_oss_config")
-public class SysOssConfig extends BaseEntity {
-
-    /**
-     * 涓诲缓
-     */
-    @TableId(value = "oss_config_id")
-    private Long ossConfigId;
-
-    /**
-     * 閰嶇疆key
-     */
-    private String configKey;
-
-    /**
-     * accessKey
-     */
-    private String accessKey;
-
-    /**
-     * 绉橀挜
-     */
-    private String secretKey;
-
-    /**
-     * 妗跺悕绉�
-     */
-    private String bucketName;
-
-    /**
-     * 鍓嶇紑
-     */
-    private String prefix;
-
-    /**
-     * 璁块棶绔欑偣
-     */
-    private String endpoint;
-
-    /**
-     * 鑷畾涔夊煙鍚�
-     */
-    private String domain;
-
-    /**
-     * 鏄惁https锛�0鍚� 1鏄級
-     */
-    private String isHttps;
-
-    /**
-     * 鍩�
-     */
-    private String region;
-
-    /**
-     * 鏄惁榛樿锛�0=鏄�,1=鍚︼級
-     */
-    private String status;
-
-    /**
-     * 鎵╁睍瀛楁
-     */
-    private String ext1;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 妗舵潈闄愮被鍨�(0private 1public 2custom)
-     */
-    private String accessPolicy;
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
deleted file mode 100644
index a751c74..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-
-/**
- * 宀椾綅琛� sys_post
- *
- * @author Lion Li
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_post")
-@ExcelIgnoreUnannotated
-public class SysPost extends BaseEntity {
-
-    /**
-     * 宀椾綅搴忓彿
-     */
-    @ExcelProperty(value = "宀椾綅搴忓彿")
-    @TableId(value = "post_id")
-    private Long postId;
-
-    /**
-     * 宀椾綅缂栫爜
-     */
-    @ExcelProperty(value = "宀椾綅缂栫爜")
-    @NotBlank(message = "宀椾綅缂栫爜涓嶈兘涓虹┖")
-    @Size(min = 0, max = 64, message = "宀椾綅缂栫爜闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String postCode;
-
-    /**
-     * 宀椾綅鍚嶇О
-     */
-    @ExcelProperty(value = "宀椾綅鍚嶇О")
-    @NotBlank(message = "宀椾綅鍚嶇О涓嶈兘涓虹┖")
-    @Size(min = 0, max = 50, message = "宀椾綅鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String postName;
-
-    /**
-     * 宀椾綅鎺掑簭
-     */
-    @ExcelProperty(value = "宀椾綅鎺掑簭")
-    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
-    private Integer postSort;
-
-    /**
-     * 鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    @ExcelProperty(value = "鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_normal_disable")
-    private String status;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 鐢ㄦ埛鏄惁瀛樺湪姝ゅ矖浣嶆爣璇� 榛樿涓嶅瓨鍦�
-     */
-    @TableField(exist = false)
-    private boolean flag = false;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
deleted file mode 100644
index c63f324..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRole.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import java.util.Set;
-
-/**
- * 瑙掕壊琛� sys_role
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_role")
-@ExcelIgnoreUnannotated
-public class SysRole extends BaseEntity {
-
-    /**
-     * 瑙掕壊ID
-     */
-    @ExcelProperty(value = "瑙掕壊搴忓彿")
-    @TableId(value = "role_id")
-    private Long roleId;
-
-    /**
-     * 瑙掕壊鍚嶇О
-     */
-    @ExcelProperty(value = "瑙掕壊鍚嶇О")
-    @NotBlank(message = "瑙掕壊鍚嶇О涓嶈兘涓虹┖")
-    @Size(min = 0, max = 30, message = "瑙掕壊鍚嶇О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String roleName;
-
-    /**
-     * 瑙掕壊鏉冮檺
-     */
-    @ExcelProperty(value = "瑙掕壊鏉冮檺")
-    @NotBlank(message = "鏉冮檺瀛楃涓嶈兘涓虹┖")
-    @Size(min = 0, max = 100, message = "鏉冮檺瀛楃闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String roleKey;
-
-    /**
-     * 瑙掕壊鎺掑簭
-     */
-    @ExcelProperty(value = "瑙掕壊鎺掑簭")
-    @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
-    private Integer roleSort;
-
-    /**
-     * 鏁版嵁鑼冨洿锛�1锛氭墍鏈夋暟鎹潈闄愶紱2锛氳嚜瀹氫箟鏁版嵁鏉冮檺锛�3锛氭湰閮ㄩ棬鏁版嵁鏉冮檺锛�4锛氭湰閮ㄩ棬鍙婁互涓嬫暟鎹潈闄愶紱5锛氫粎鏈汉鏁版嵁鏉冮檺锛�
-     */
-    @ExcelProperty(value = "鏁版嵁鑼冨洿", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "1=鎵�鏈夋暟鎹潈闄�,2=鑷畾涔夋暟鎹潈闄�,3=鏈儴闂ㄦ暟鎹潈闄�,4=鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺,5=浠呮湰浜烘暟鎹潈闄�")
-    private String dataScope;
-
-    /**
-     * 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙 0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀猴級
-     */
-    private Boolean menuCheckStrictly;
-
-    /**
-     * 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀� 锛�
-     */
-    private Boolean deptCheckStrictly;
-
-    /**
-     * 瑙掕壊鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    @ExcelProperty(value = "瑙掕壊鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_normal_disable")
-    private String status;
-
-    /**
-     * 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�
-     */
-    @TableLogic
-    private String delFlag;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 鐢ㄦ埛鏄惁瀛樺湪姝よ鑹叉爣璇� 榛樿涓嶅瓨鍦�
-     */
-    @TableField(exist = false)
-    private boolean flag = false;
-
-    /**
-     * 鑿滃崟缁�
-     */
-    @TableField(exist = false)
-    private Long[] menuIds;
-
-    /**
-     * 閮ㄩ棬缁勶紙鏁版嵁鏉冮檺锛�
-     */
-    @TableField(exist = false)
-    private Long[] deptIds;
-
-    /**
-     * 瑙掕壊鑿滃崟鏉冮檺
-     */
-    @TableField(exist = false)
-    private Set<String> permissions;
-
-    public SysRole(Long roleId) {
-        this.roleId = roleId;
-    }
-
-    public boolean isAdmin() {
-        return UserConstants.ADMIN_ID.equals(this.roleId);
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
deleted file mode 100644
index 07471c7..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUser.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.ruoyi.system.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.ruoyi.common.annotation.Sensitive;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.enums.SensitiveStrategy;
-import com.ruoyi.common.xss.Xss;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 鐢ㄦ埛瀵硅薄 sys_user
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@TableName("sys_user")
-public class SysUser extends BaseEntity {
-
-    /**
-     * 鐢ㄦ埛ID
-     */
-    @TableId(value = "user_id")
-    private Long userId;
-
-    /**
-     * 閮ㄩ棬ID
-     */
-    private Long deptId;
-
-    /**
-     * 鐢ㄦ埛璐﹀彿
-     */
-    @Xss(message = "鐢ㄦ埛璐﹀彿涓嶈兘鍖呭惈鑴氭湰瀛楃")
-    @NotBlank(message = "鐢ㄦ埛璐﹀彿涓嶈兘涓虹┖")
-    @Size(min = 0, max = 30, message = "鐢ㄦ埛璐﹀彿闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String userName;
-
-    /**
-     * 鐢ㄦ埛鏄电О
-     */
-    @Xss(message = "鐢ㄦ埛鏄电О涓嶈兘鍖呭惈鑴氭湰瀛楃")
-    @Size(min = 0, max = 30, message = "鐢ㄦ埛鏄电О闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String nickName;
-
-    /**
-     * 鐢ㄦ埛绫诲瀷锛坰ys_user绯荤粺鐢ㄦ埛锛�
-     */
-    private String userType;
-
-    /**
-     * 鐢ㄦ埛閭
-     */
-    @Sensitive(strategy = SensitiveStrategy.EMAIL)
-    @Email(message = "閭鏍煎紡涓嶆纭�")
-    @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃{max}涓瓧绗�")
-    private String email;
-
-    /**
-     * 鎵嬫満鍙风爜
-     */
-    @Sensitive(strategy = SensitiveStrategy.PHONE)
-    private String phonenumber;
-
-    /**
-     * 鐢ㄦ埛鎬у埆
-     */
-    private String sex;
-
-    /**
-     * 鐢ㄦ埛澶村儚
-     */
-    private String avatar;
-
-    /**
-     * 瀵嗙爜
-     */
-    @TableField(
-        insertStrategy = FieldStrategy.NOT_EMPTY,
-        updateStrategy = FieldStrategy.NOT_EMPTY,
-        whereStrategy = FieldStrategy.NOT_EMPTY
-    )
-    private String password;
-
-    /**
-     * 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    private String status;
-
-    /**
-     * 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�
-     */
-    @TableLogic
-    private String delFlag;
-
-    /**
-     * 鏈�鍚庣櫥褰旾P
-     */
-    private String loginIp;
-
-    /**
-     * 鏈�鍚庣櫥褰曟椂闂�
-     */
-    private Date loginDate;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 閮ㄩ棬瀵硅薄
-     */
-    @TableField(exist = false)
-    private SysDept dept;
-
-    /**
-     * 瑙掕壊瀵硅薄
-     */
-    @TableField(exist = false)
-    private List<SysRole> roles;
-
-    /**
-     * 瑙掕壊缁�
-     */
-    @TableField(exist = false)
-    private Long[] roleIds;
-
-    /**
-     * 宀椾綅缁�
-     */
-    @TableField(exist = false)
-    private Long[] postIds;
-
-    /**
-     * 鏁版嵁鏉冮檺 褰撳墠瑙掕壊ID
-     */
-    @TableField(exist = false)
-    private Long roleId;
-
-    public SysUser(Long userId) {
-        this.userId = userId;
-    }
-
-    public boolean isAdmin() {
-        return UserConstants.ADMIN_ID.equals(this.userId);
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java
deleted file mode 100644
index 3f5ab4a..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.ruoyi.system.domain.bo;
-
-import com.ruoyi.common.core.domain.BaseEntity;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * OSS瀵硅薄瀛樺偍鍒嗛〉鏌ヨ瀵硅薄 sys_oss
- *
- * @author Lion Li
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class SysOssBo extends BaseEntity {
-
-    /**
-     * 鏂囦欢鍚�
-     */
-    private String fileName;
-    /**
-     * 鍘熷悕
-     */
-    private String originalName;
-    /**
-     * 鏂囦欢鍚庣紑鍚�
-     */
-    private String fileSuffix;
-    /**
-     * URL鍦板潃
-     */
-    private String url;
-    /**
-     * 鏈嶅姟鍟�
-     */
-    private String service;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
deleted file mode 100644
index b717837..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.ruoyi.system.domain.bo;
-
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-
-/**
- * 瀵硅薄瀛樺偍閰嶇疆涓氬姟瀵硅薄 sys_oss_config
- *
- * @author Lion Li
- * @author 瀛よ垷鐑熼洦
- * @date 2021-08-13
- */
-
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class SysOssConfigBo extends BaseEntity {
-
-    /**
-     * 涓诲缓
-     */
-    @NotNull(message = "涓诲缓涓嶈兘涓虹┖", groups = {EditGroup.class})
-    private Long ossConfigId;
-
-    /**
-     * 閰嶇疆key
-     */
-    @NotBlank(message = "閰嶇疆key涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    @Size(min = 2, max = 100, message = "configKey闀垮害蹇呴』浠嬩簬{min}鍜寋max} 涔嬮棿")
-    private String configKey;
-
-    /**
-     * accessKey
-     */
-    @NotBlank(message = "accessKey涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    @Size(min = 2, max = 100, message = "accessKey闀垮害蹇呴』浠嬩簬{min}鍜寋max} 涔嬮棿")
-    private String accessKey;
-
-    /**
-     * 绉橀挜
-     */
-    @NotBlank(message = "secretKey涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    @Size(min = 2, max = 100, message = "secretKey闀垮害蹇呴』浠嬩簬{min}鍜寋max} 涔嬮棿")
-    private String secretKey;
-
-    /**
-     * 妗跺悕绉�
-     */
-    @NotBlank(message = "妗跺悕绉颁笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
-    @Size(min = 2, max = 100, message = "bucketName闀垮害蹇呴』浠嬩簬{min}鍜寋max}涔嬮棿")
-    private String bucketName;
-
-    /**
-     * 鍓嶇紑
-     */
-    private String prefix;
-
-    /**
-     * 璁块棶绔欑偣
-     */
-    @NotBlank(message = "璁块棶绔欑偣涓嶈兘涓虹┖", groups = {AddGroup.class, EditGroup.class})
-    @Size(min = 2, max = 100, message = "endpoint闀垮害蹇呴』浠嬩簬{min}鍜寋max}涔嬮棿")
-    private String endpoint;
-
-    /**
-     * 鑷畾涔夊煙鍚�
-     */
-    private String domain;
-
-    /**
-     * 鏄惁https锛圷=鏄�,N=鍚︼級
-     */
-    private String isHttps;
-
-    /**
-     * 鏄惁榛樿锛�0=鏄�,1=鍚︼級
-     */
-    private String status;
-
-    /**
-     * 鍩�
-     */
-    private String region;
-
-    /**
-     * 鎵╁睍瀛楁
-     */
-    private String ext1;
-
-    /**
-     * 澶囨敞
-     */
-    private String remark;
-
-    /**
-     * 妗舵潈闄愮被鍨�(0private 1public 2custom)
-     */
-    @NotBlank(message = "妗舵潈闄愮被鍨嬩笉鑳戒负绌�", groups = {AddGroup.class, EditGroup.class})
-    private String accessPolicy;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java
deleted file mode 100644
index ec1f02e..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.ruoyi.system.domain.vo;
-
-import com.ruoyi.common.utils.StringUtils;
-import lombok.Data;
-
-/**
- * 璺敱鏄剧ず淇℃伅
- *
- * @author ruoyi
- */
-
-@Data
-public class MetaVo {
-
-    /**
-     * 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
-     */
-    private String title;
-
-    /**
-     * 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
-     */
-    private String icon;
-
-    /**
-     * 璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive>缂撳瓨
-     */
-    private boolean noCache;
-
-    /**
-     * 鍐呴摼鍦板潃锛坔ttp(s)://寮�澶达級
-     */
-    private String link;
-
-    public MetaVo(String title, String icon) {
-        this.title = title;
-        this.icon = icon;
-    }
-
-    public MetaVo(String title, String icon, boolean noCache) {
-        this.title = title;
-        this.icon = icon;
-        this.noCache = noCache;
-    }
-
-    public MetaVo(String title, String icon, String link) {
-        this.title = title;
-        this.icon = icon;
-        this.link = link;
-    }
-
-    public MetaVo(String title, String icon, boolean noCache, String link) {
-        this.title = title;
-        this.icon = icon;
-        this.noCache = noCache;
-        if (StringUtils.ishttp(link)) {
-            this.link = link;
-        }
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java
deleted file mode 100644
index 5556cd4..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.ruoyi.system.domain.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * 鐢ㄦ埛瀵硅薄瀵煎嚭VO
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-public class SysUserExportVo implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鐢ㄦ埛ID
-     */
-    @ExcelProperty(value = "鐢ㄦ埛搴忓彿")
-    private Long userId;
-
-    /**
-     * 鐢ㄦ埛璐﹀彿
-     */
-    @ExcelProperty(value = "鐧诲綍鍚嶇О")
-    private String userName;
-
-    /**
-     * 鐢ㄦ埛鏄电О
-     */
-    @ExcelProperty(value = "鐢ㄦ埛鍚嶇О")
-    private String nickName;
-
-    /**
-     * 鐢ㄦ埛閭
-     */
-    @ExcelProperty(value = "鐢ㄦ埛閭")
-    private String email;
-
-    /**
-     * 鎵嬫満鍙风爜
-     */
-    @ExcelProperty(value = "鎵嬫満鍙风爜")
-    private String phonenumber;
-
-    /**
-     * 鐢ㄦ埛鎬у埆
-     */
-    @ExcelProperty(value = "鐢ㄦ埛鎬у埆", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_user_sex")
-    private String sex;
-
-    /**
-     * 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    @ExcelProperty(value = "甯愬彿鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_normal_disable")
-    private String status;
-
-    /**
-     * 鏈�鍚庣櫥褰旾P
-     */
-    @ExcelProperty(value = "鏈�鍚庣櫥褰旾P")
-    private String loginIp;
-
-    /**
-     * 鏈�鍚庣櫥褰曟椂闂�
-     */
-    @ExcelProperty(value = "鏈�鍚庣櫥褰曟椂闂�")
-    private Date loginDate;
-
-    /**
-     * 閮ㄩ棬鍚嶇О
-     */
-    @ExcelProperty(value = "閮ㄩ棬鍚嶇О")
-    private String deptName;
-
-    /**
-     * 璐熻矗浜�
-     */
-    @ExcelProperty(value = "閮ㄩ棬璐熻矗浜�")
-    private String leader;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java
deleted file mode 100644
index 50158da..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserImportVo.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.ruoyi.system.domain.vo;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelDictConvert;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.io.Serial;
-import java.io.Serializable;
-
-/**
- * 鐢ㄦ埛瀵硅薄瀵煎叆VO
- *
- * @author Lion Li
- */
-
-@Data
-@NoArgsConstructor
-// @Accessors(chain = true) // 瀵煎叆涓嶅厑璁镐娇鐢� 浼氭壘涓嶅埌set鏂规硶
-public class SysUserImportVo implements Serializable {
-
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 鐢ㄦ埛ID
-     */
-    @ExcelProperty(value = "鐢ㄦ埛搴忓彿")
-    private Long userId;
-
-    /**
-     * 閮ㄩ棬ID
-     */
-    @ExcelProperty(value = "閮ㄩ棬缂栧彿")
-    private Long deptId;
-
-    /**
-     * 鐢ㄦ埛璐﹀彿
-     */
-    @ExcelProperty(value = "鐧诲綍鍚嶇О")
-    private String userName;
-
-    /**
-     * 鐢ㄦ埛鏄电О
-     */
-    @ExcelProperty(value = "鐢ㄦ埛鍚嶇О")
-    private String nickName;
-
-    /**
-     * 鐢ㄦ埛閭
-     */
-    @ExcelProperty(value = "鐢ㄦ埛閭")
-    private String email;
-
-    /**
-     * 鎵嬫満鍙风爜
-     */
-    @ExcelProperty(value = "鎵嬫満鍙风爜")
-    private String phonenumber;
-
-    /**
-     * 鐢ㄦ埛鎬у埆
-     */
-    @ExcelProperty(value = "鐢ㄦ埛鎬у埆", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_user_sex")
-    private String sex;
-
-    /**
-     * 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�
-     */
-    @ExcelProperty(value = "甯愬彿鐘舵��", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "sys_normal_disable")
-    private String status;
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java
deleted file mode 100644
index 0449f5f..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.ruoyi.system.listener;
-
-import cn.dev33.satoken.secure.BCrypt;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.alibaba.excel.context.AnalysisContext;
-import com.alibaba.excel.event.AnalysisEventListener;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.excel.ExcelListener;
-import com.ruoyi.common.excel.ExcelResult;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.ValidatorUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.system.domain.vo.SysUserImportVo;
-import com.ruoyi.system.service.ISysConfigService;
-import com.ruoyi.system.service.ISysUserService;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.List;
-
-/**
- * 绯荤粺鐢ㄦ埛鑷畾涔夊鍏�
- *
- * @author Lion Li
- */
-@Slf4j
-public class SysUserImportListener extends AnalysisEventListener<SysUserImportVo> implements ExcelListener<SysUserImportVo> {
-
-    private final ISysUserService userService;
-
-    private final String password;
-
-    private final Boolean isUpdateSupport;
-
-    private final String operName;
-
-    private int successNum = 0;
-    private int failureNum = 0;
-    private final StringBuilder successMsg = new StringBuilder();
-    private final StringBuilder failureMsg = new StringBuilder();
-
-    public SysUserImportListener(Boolean isUpdateSupport) {
-        String initPassword = SpringUtils.getBean(ISysConfigService.class).selectConfigByKey("sys.user.initPassword");
-        this.userService = SpringUtils.getBean(ISysUserService.class);
-        this.password = BCrypt.hashpw(initPassword);
-        this.isUpdateSupport = isUpdateSupport;
-        this.operName = LoginHelper.getUsername();
-    }
-
-    @Override
-    public void invoke(SysUserImportVo userVo, AnalysisContext context) {
-        SysUser user = this.userService.selectUserByUserName(userVo.getUserName());
-        try {
-            // 楠岃瘉鏄惁瀛樺湪杩欎釜鐢ㄦ埛
-            if (ObjectUtil.isNull(user)) {
-                user = BeanUtil.toBean(userVo, SysUser.class);
-                ValidatorUtils.validate(user);
-                user.setPassword(password);
-                user.setCreateBy(operName);
-                userService.insertUser(user);
-                successNum++;
-                successMsg.append("<br/>").append(successNum).append("銆佽处鍙� ").append(user.getUserName()).append(" 瀵煎叆鎴愬姛");
-            } else if (isUpdateSupport) {
-                Long userId = user.getUserId();
-                user = BeanUtil.toBean(userVo, SysUser.class);
-                user.setUserId(userId);
-                ValidatorUtils.validate(user);
-                userService.checkUserAllowed(user);
-                userService.checkUserDataScope(user.getUserId());
-                user.setUpdateBy(operName);
-                userService.updateUser(user);
-                successNum++;
-                successMsg.append("<br/>").append(successNum).append("銆佽处鍙� ").append(user.getUserName()).append(" 鏇存柊鎴愬姛");
-            } else {
-                failureNum++;
-                failureMsg.append("<br/>").append(failureNum).append("銆佽处鍙� ").append(user.getUserName()).append(" 宸插瓨鍦�");
-            }
-        } catch (Exception e) {
-            failureNum++;
-            String msg = "<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆澶辫触锛�";
-            failureMsg.append(msg).append(e.getMessage());
-            log.error(msg, e);
-        }
-    }
-
-    @Override
-    public void doAfterAllAnalysed(AnalysisContext context) {
-
-    }
-
-    @Override
-    public ExcelResult<SysUserImportVo> getExcelResult() {
-        return new ExcelResult<SysUserImportVo>() {
-
-            @Override
-            public String getAnalysis() {
-                if (failureNum > 0) {
-                    failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細");
-                    throw new ServiceException(failureMsg.toString());
-                } else {
-                    successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�");
-                }
-                return successMsg.toString();
-            }
-
-            @Override
-            public List<SysUserImportVo> getList() {
-                return null;
-            }
-
-            @Override
-            public List<String> getErrorList() {
-                return null;
-            }
-        };
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
deleted file mode 100644
index 13cce2d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysConfig;
-
-/**
- * 鍙傛暟閰嶇疆 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysConfigMapper extends BaseMapperPlus<SysConfigMapper, SysConfig, SysConfig> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
deleted file mode 100644
index fdafbca..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.ruoyi.common.annotation.DataColumn;
-import com.ruoyi.common.annotation.DataPermission;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 閮ㄩ棬绠$悊 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysDeptMapper extends BaseMapperPlus<SysDeptMapper, SysDept, SysDept> {
-
-    /**
-     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
-     *
-     * @param queryWrapper 鏌ヨ鏉′欢
-     * @return 閮ㄩ棬淇℃伅闆嗗悎
-     */
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "dept_id")
-    })
-    List<SysDept> selectDeptList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
-
-    /**
-     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
-     *
-     * @param roleId            瑙掕壊ID
-     * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
-     * @return 閫変腑閮ㄩ棬鍒楄〃
-     */
-    List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
deleted file mode 100644
index c9ae69e..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.system.domain.SysDictData;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-
-import java.util.List;
-
-/**
- * 瀛楀吀琛� 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysDictDataMapper extends BaseMapperPlus<SysDictDataMapper, SysDictData, SysDictData> {
-
-    default List<SysDictData> selectDictDataByType(String dictType) {
-        return selectList(
-            new LambdaQueryWrapper<SysDictData>()
-                .eq(SysDictData::getStatus, UserConstants.DICT_NORMAL)
-                .eq(SysDictData::getDictType, dictType)
-                .orderByAsc(SysDictData::getDictSort));
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
deleted file mode 100644
index c1a25a6..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.system.domain.SysDictType;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-
-/**
- * 瀛楀吀琛� 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysDictTypeMapper extends BaseMapperPlus<SysDictTypeMapper, SysDictType, SysDictType> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
deleted file mode 100644
index b74f3ff..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysLogininfor;
-
-/**
- * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysLogininforMapper extends BaseMapperPlus<SysLogininforMapper, SysLogininfor, SysLogininfor> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
deleted file mode 100644
index 157bb53..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.system.domain.SysMenu;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 鑿滃崟琛� 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysMenuMapper extends BaseMapperPlus<SysMenuMapper, SysMenu, SysMenu> {
-
-    /**
-     * 鏍规嵁鐢ㄦ埛鎵�鏈夋潈闄�
-     *
-     * @return 鏉冮檺鍒楄〃
-     */
-    List<String> selectMenuPerms();
-
-    /**
-     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
-     *
-     * @param queryWrapper 鏌ヨ鏉′欢
-     * @return 鑿滃崟鍒楄〃
-     */
-    List<SysMenu> selectMenuListByUserId(@Param(Constants.WRAPPER) Wrapper<SysMenu> queryWrapper);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鏉冮檺鍒楄〃
-     */
-    List<String> selectMenuPermsByUserId(Long userId);
-
-    /**
-     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 鏉冮檺鍒楄〃
-     */
-    List<String> selectMenuPermsByRoleId(Long roleId);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
-     *
-     * @return 鑿滃崟鍒楄〃
-     */
-    default List<SysMenu> selectMenuTreeAll() {
-        LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<SysMenu>()
-            .in(SysMenu::getMenuType, UserConstants.TYPE_DIR, UserConstants.TYPE_MENU)
-            .eq(SysMenu::getStatus, UserConstants.MENU_NORMAL)
-            .orderByAsc(SysMenu::getParentId)
-            .orderByAsc(SysMenu::getOrderNum);
-        return this.selectList(lqw);
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鑿滃崟鍒楄〃
-     */
-    List<SysMenu> selectMenuTreeByUserId(Long userId);
-
-    /**
-     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
-     *
-     * @param roleId            瑙掕壊ID
-     * @param menuCheckStrictly 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
-     * @return 閫変腑鑿滃崟鍒楄〃
-     */
-    List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
deleted file mode 100644
index 69fa3ba..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysNotice;
-
-/**
- * 閫氱煡鍏憡琛� 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysNoticeMapper extends BaseMapperPlus<SysNoticeMapper, SysNotice, SysNotice> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
deleted file mode 100644
index bbb265d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysOperLog;
-
-/**
- * 鎿嶄綔鏃ュ織 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysOperLogMapper extends BaseMapperPlus<SysOperLogMapper, SysOperLog, SysOperLog> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java
deleted file mode 100644
index 72f29a7..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssConfigMapper.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysOssConfig;
-import com.ruoyi.system.domain.vo.SysOssConfigVo;
-
-/**
- * 瀵硅薄瀛樺偍閰嶇疆Mapper鎺ュ彛
- *
- * @author Lion Li
- * @author 瀛よ垷鐑熼洦
- * @date 2021-08-13
- */
-public interface SysOssConfigMapper extends BaseMapperPlus<SysOssConfigMapper, SysOssConfig, SysOssConfigVo> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java
deleted file mode 100644
index edbaed6..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOssMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysOss;
-import com.ruoyi.system.domain.vo.SysOssVo;
-
-/**
- * 鏂囦欢涓婁紶 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysOssMapper extends BaseMapperPlus<SysOssMapper, SysOss, SysOssVo> {
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
deleted file mode 100644
index 7330494..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysPost;
-
-import java.util.List;
-
-/**
- * 宀椾綅淇℃伅 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysPostMapper extends BaseMapperPlus<SysPostMapper, SysPost, SysPost> {
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 閫変腑宀椾綅ID鍒楄〃
-     */
-    List<Long> selectPostListByUserId(Long userId);
-
-    /**
-     * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 缁撴灉
-     */
-    List<SysPost> selectPostsByUserName(String userName);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
deleted file mode 100644
index 0428d98..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysRoleDept;
-
-/**
- * 瑙掕壊涓庨儴闂ㄥ叧鑱旇〃 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysRoleDeptMapper extends BaseMapperPlus<SysRoleDeptMapper, SysRoleDept, SysRoleDept> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
deleted file mode 100644
index ff4f672..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.annotation.DataColumn;
-import com.ruoyi.common.annotation.DataPermission;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 瑙掕壊琛� 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysRoleMapper extends BaseMapperPlus<SysRoleMapper, SysRole, SysRole> {
-
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "d.dept_id")
-    })
-    Page<SysRole> selectPageRoleList(@Param("page") Page<SysRole> page, @Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
-     *
-     * @param queryWrapper 鏌ヨ鏉′欢
-     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
-     */
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "d.dept_id")
-    })
-    List<SysRole> selectRoleList(@Param(Constants.WRAPPER) Wrapper<SysRole> queryWrapper);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 瑙掕壊鍒楄〃
-     */
-    List<SysRole> selectRolePermissionByUserId(Long userId);
-
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 閫変腑瑙掕壊ID鍒楄〃
-     */
-    List<Long> selectRoleListByUserId(Long userId);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 瑙掕壊鍒楄〃
-     */
-    List<SysRole> selectRolesByUserName(String userName);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
deleted file mode 100644
index e9987cc..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysRoleMenu;
-
-/**
- * 瑙掕壊涓庤彍鍗曞叧鑱旇〃 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysRoleMenuMapper extends BaseMapperPlus<SysRoleMenuMapper, SysRoleMenu, SysRoleMenu> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
deleted file mode 100644
index 5e99685..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.toolkit.Constants;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.annotation.DataColumn;
-import com.ruoyi.common.annotation.DataPermission;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 鐢ㄦ埛琛� 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysUserMapper extends BaseMapperPlus<SysUserMapper, SysUser, SysUser> {
-
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "d.dept_id"),
-        @DataColumn(key = "userName", value = "u.user_id")
-    })
-    Page<SysUser> selectPageUserList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
-     *
-     * @param queryWrapper 鏌ヨ鏉′欢
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "d.dept_id"),
-        @DataColumn(key = "userName", value = "u.user_id")
-    })
-    List<SysUser> selectUserList(@Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸查厤鐢ㄦ埛瑙掕壊鍒楄〃
-     *
-     * @param queryWrapper 鏌ヨ鏉′欢
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "d.dept_id"),
-        @DataColumn(key = "userName", value = "u.user_id")
-    })
-    Page<SysUser> selectAllocatedList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
-     *
-     * @param queryWrapper 鏌ヨ鏉′欢
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    @DataPermission({
-        @DataColumn(key = "deptName", value = "d.dept_id"),
-        @DataColumn(key = "userName", value = "u.user_id")
-    })
-    Page<SysUser> selectUnallocatedList(@Param("page") Page<SysUser> page, @Param(Constants.WRAPPER) Wrapper<SysUser> queryWrapper);
-
-    /**
-     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    SysUser selectUserByUserName(String userName);
-
-    /**
-     * 閫氳繃鎵嬫満鍙锋煡璇㈢敤鎴�
-     *
-     * @param phonenumber 鎵嬫満鍙�
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    SysUser selectUserByPhonenumber(String phonenumber);
-
-    /**
-     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    SysUser selectUserById(Long userId);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
deleted file mode 100644
index 1af9b24..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysUserPost;
-
-/**
- * 鐢ㄦ埛涓庡矖浣嶅叧鑱旇〃 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysUserPostMapper extends BaseMapperPlus<SysUserPostMapper, SysUserPost, SysUserPost> {
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
deleted file mode 100644
index be8fb8f..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.ruoyi.system.mapper;
-
-import com.ruoyi.common.core.mapper.BaseMapperPlus;
-import com.ruoyi.system.domain.SysUserRole;
-
-import java.util.List;
-
-/**
- * 鐢ㄦ埛涓庤鑹插叧鑱旇〃 鏁版嵁灞�
- *
- * @author Lion Li
- */
-public interface SysUserRoleMapper extends BaseMapperPlus<SysUserRoleMapper, SysUserRole, SysUserRole> {
-
-    List<Long> selectUserIdsByRoleId(Long roleId);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java
deleted file mode 100644
index e9ad6ee..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/SystemApplicationRunner.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.system.runner;
-
-import com.ruoyi.common.config.RuoYiConfig;
-import com.ruoyi.system.service.ISysConfigService;
-import com.ruoyi.system.service.ISysDictTypeService;
-import com.ruoyi.system.service.ISysOssConfigService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.stereotype.Component;
-
-/**
- * 鍒濆鍖� system 妯″潡瀵瑰簲涓氬姟鏁版嵁
- *
- * @author Lion Li
- */
-@Slf4j
-@RequiredArgsConstructor
-@Component
-public class SystemApplicationRunner implements ApplicationRunner {
-
-    private final RuoYiConfig ruoyiConfig;
-    private final ISysConfigService configService;
-    private final ISysDictTypeService dictTypeService;
-    private final ISysOssConfigService ossConfigService;
-
-    @Override
-    public void run(ApplicationArguments args) throws Exception {
-        ossConfigService.init();
-        log.info("鍒濆鍖朞SS閰嶇疆鎴愬姛");
-        if (ruoyiConfig.isCacheLazy()) {
-            return;
-        }
-        configService.loadingConfigCache();
-        log.info("鍔犺浇鍙傛暟缂撳瓨鏁版嵁鎴愬姛");
-        dictTypeService.loadingDictCache();
-        log.info("鍔犺浇瀛楀吀缂撳瓨鏁版嵁鎴愬姛");
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
deleted file mode 100644
index adcb5d3..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysConfig;
-
-import java.util.List;
-
-/**
- * 鍙傛暟閰嶇疆 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface ISysConfigService {
-
-
-    TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery);
-
-    /**
-     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
-     *
-     * @param configId 鍙傛暟閰嶇疆ID
-     * @return 鍙傛暟閰嶇疆淇℃伅
-     */
-    SysConfig selectConfigById(Long configId);
-
-    /**
-     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
-     *
-     * @param configKey 鍙傛暟閿悕
-     * @return 鍙傛暟閿��
-     */
-    String selectConfigByKey(String configKey);
-
-    /**
-     * 鑾峰彇楠岃瘉鐮佸紑鍏�
-     *
-     * @return true寮�鍚紝false鍏抽棴
-     */
-    boolean selectCaptchaEnabled();
-
-    /**
-     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 鍙傛暟閰嶇疆闆嗗悎
-     */
-    List<SysConfig> selectConfigList(SysConfig config);
-
-    /**
-     * 鏂板鍙傛暟閰嶇疆
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 缁撴灉
-     */
-    String insertConfig(SysConfig config);
-
-    /**
-     * 淇敼鍙傛暟閰嶇疆
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 缁撴灉
-     */
-    String updateConfig(SysConfig config);
-
-    /**
-     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
-     *
-     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
-     */
-    void deleteConfigByIds(Long[] configIds);
-
-    /**
-     * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
-     */
-    void loadingConfigCache();
-
-    /**
-     * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
-     */
-    void clearConfigCache();
-
-    /**
-     * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
-     */
-    void resetConfigCache();
-
-    /**
-     * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
-     *
-     * @param config 鍙傛暟淇℃伅
-     * @return 缁撴灉
-     */
-    String checkConfigKeyUnique(SysConfig config);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
deleted file mode 100644
index 904367d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysDictData;
-import com.ruoyi.common.core.page.TableDataInfo;
-
-import java.util.List;
-
-/**
- * 瀛楀吀 涓氬姟灞�
- *
- * @author Lion Li
- */
-public interface ISysDictDataService {
-
-
-    TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData, PageQuery pageQuery);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
-     *
-     * @param dictData 瀛楀吀鏁版嵁淇℃伅
-     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
-     */
-    List<SysDictData> selectDictDataList(SysDictData dictData);
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictValue 瀛楀吀閿��
-     * @return 瀛楀吀鏍囩
-     */
-    String selectDictLabel(String dictType, String dictValue);
-
-    /**
-     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
-     *
-     * @param dictCode 瀛楀吀鏁版嵁ID
-     * @return 瀛楀吀鏁版嵁
-     */
-    SysDictData selectDictDataById(Long dictCode);
-
-    /**
-     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
-     */
-    void deleteDictDataByIds(Long[] dictCodes);
-
-    /**
-     * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param dictData 瀛楀吀鏁版嵁淇℃伅
-     * @return 缁撴灉
-     */
-    List<SysDictData> insertDictData(SysDictData dictData);
-
-    /**
-     * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param dictData 瀛楀吀鏁版嵁淇℃伅
-     * @return 缁撴灉
-     */
-    List<SysDictData> updateDictData(SysDictData dictData);
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
deleted file mode 100644
index d7e31a6..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysDictData;
-import com.ruoyi.system.domain.SysDictType;
-import com.ruoyi.common.core.page.TableDataInfo;
-
-import java.util.List;
-
-/**
- * 瀛楀吀 涓氬姟灞�
- *
- * @author Lion Li
- */
-public interface ISysDictTypeService {
-
-
-    TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
-     *
-     * @param dictType 瀛楀吀绫诲瀷淇℃伅
-     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
-     */
-    List<SysDictType> selectDictTypeList(SysDictType dictType);
-
-    /**
-     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
-     *
-     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
-     */
-    List<SysDictType> selectDictTypeAll();
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
-     *
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
-     */
-    List<SysDictData> selectDictDataByType(String dictType);
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
-     *
-     * @param dictId 瀛楀吀绫诲瀷ID
-     * @return 瀛楀吀绫诲瀷
-     */
-    SysDictType selectDictTypeById(Long dictId);
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
-     *
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 瀛楀吀绫诲瀷
-     */
-    SysDictType selectDictTypeByType(String dictType);
-
-    /**
-     * 鎵归噺鍒犻櫎瀛楀吀淇℃伅
-     *
-     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
-     */
-    void deleteDictTypeByIds(Long[] dictIds);
-
-    /**
-     * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
-     */
-    void loadingDictCache();
-
-    /**
-     * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
-     */
-    void clearDictCache();
-
-    /**
-     * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
-     */
-    void resetDictCache();
-
-    /**
-     * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
-     *
-     * @param dictType 瀛楀吀绫诲瀷淇℃伅
-     * @return 缁撴灉
-     */
-    List<SysDictData> insertDictType(SysDictType dictType);
-
-    /**
-     * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
-     *
-     * @param dictType 瀛楀吀绫诲瀷淇℃伅
-     * @return 缁撴灉
-     */
-    List<SysDictData> updateDictType(SysDictType dictType);
-
-    /**
-     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
-     *
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 缁撴灉
-     */
-    String checkDictTypeUnique(SysDictType dictType);
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
deleted file mode 100644
index f63c7dd..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysLogininfor;
-
-import java.util.List;
-
-/**
- * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface ISysLogininforService {
-
-
-    TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery);
-
-    /**
-     * 鏂板绯荤粺鐧诲綍鏃ュ織
-     *
-     * @param logininfor 璁块棶鏃ュ織瀵硅薄
-     */
-    void insertLogininfor(SysLogininfor logininfor);
-
-    /**
-     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
-     *
-     * @param logininfor 璁块棶鏃ュ織瀵硅薄
-     * @return 鐧诲綍璁板綍闆嗗悎
-     */
-    List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
-
-    /**
-     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
-     *
-     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
-     * @return 缁撴灉
-     */
-    int deleteLogininforByIds(Long[] infoIds);
-
-    /**
-     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
-     */
-    void cleanLogininfor();
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
deleted file mode 100644
index a6dbcbf..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysNotice;
-
-import java.util.List;
-
-/**
- * 鍏憡 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface ISysNoticeService {
-
-
-    TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice, PageQuery pageQuery);
-
-    /**
-     * 鏌ヨ鍏憡淇℃伅
-     *
-     * @param noticeId 鍏憡ID
-     * @return 鍏憡淇℃伅
-     */
-    SysNotice selectNoticeById(Long noticeId);
-
-    /**
-     * 鏌ヨ鍏憡鍒楄〃
-     *
-     * @param notice 鍏憡淇℃伅
-     * @return 鍏憡闆嗗悎
-     */
-    List<SysNotice> selectNoticeList(SysNotice notice);
-
-    /**
-     * 鏂板鍏憡
-     *
-     * @param notice 鍏憡淇℃伅
-     * @return 缁撴灉
-     */
-    int insertNotice(SysNotice notice);
-
-    /**
-     * 淇敼鍏憡
-     *
-     * @param notice 鍏憡淇℃伅
-     * @return 缁撴灉
-     */
-    int updateNotice(SysNotice notice);
-
-    /**
-     * 鍒犻櫎鍏憡淇℃伅
-     *
-     * @param noticeId 鍏憡ID
-     * @return 缁撴灉
-     */
-    int deleteNoticeById(Long noticeId);
-
-    /**
-     * 鎵归噺鍒犻櫎鍏憡淇℃伅
-     *
-     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
-     * @return 缁撴灉
-     */
-    int deleteNoticeByIds(Long[] noticeIds);
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
deleted file mode 100644
index 14ffcfd..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysOperLog;
-
-import java.util.List;
-
-/**
- * 鎿嶄綔鏃ュ織 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface ISysOperLogService {
-
-    TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog, PageQuery pageQuery);
-
-    /**
-     * 鏂板鎿嶄綔鏃ュ織
-     *
-     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
-     */
-    void insertOperlog(SysOperLog operLog);
-
-    /**
-     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
-     *
-     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
-     * @return 鎿嶄綔鏃ュ織闆嗗悎
-     */
-    List<SysOperLog> selectOperLogList(SysOperLog operLog);
-
-    /**
-     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
-     *
-     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
-     * @return 缁撴灉
-     */
-    int deleteOperLogByIds(Long[] operIds);
-
-    /**
-     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
-     *
-     * @param operId 鎿嶄綔ID
-     * @return 鎿嶄綔鏃ュ織瀵硅薄
-     */
-    SysOperLog selectOperLogById(Long operId);
-
-    /**
-     * 娓呯┖鎿嶄綔鏃ュ織
-     */
-    void cleanOperLog();
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java
deleted file mode 100644
index 80d874f..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.bo.SysOssConfigBo;
-import com.ruoyi.system.domain.vo.SysOssConfigVo;
-
-import java.util.Collection;
-
-/**
- * 瀵硅薄瀛樺偍閰嶇疆Service鎺ュ彛
- *
- * @author Lion Li
- * @author 瀛よ垷鐑熼洦
- * @date 2021-08-13
- */
-public interface ISysOssConfigService {
-
-    /**
-     * 鍒濆鍖朞SS閰嶇疆
-     */
-    void init();
-
-    /**
-     * 鏌ヨ鍗曚釜
-     */
-    SysOssConfigVo queryById(Long ossConfigId);
-
-    /**
-     * 鏌ヨ鍒楄〃
-     */
-    TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery);
-
-
-    /**
-     * 鏍规嵁鏂板涓氬姟瀵硅薄鎻掑叆瀵硅薄瀛樺偍閰嶇疆
-     *
-     * @param bo 瀵硅薄瀛樺偍閰嶇疆鏂板涓氬姟瀵硅薄
-     * @return
-     */
-    Boolean insertByBo(SysOssConfigBo bo);
-
-    /**
-     * 鏍规嵁缂栬緫涓氬姟瀵硅薄淇敼瀵硅薄瀛樺偍閰嶇疆
-     *
-     * @param bo 瀵硅薄瀛樺偍閰嶇疆缂栬緫涓氬姟瀵硅薄
-     * @return
-     */
-    Boolean updateByBo(SysOssConfigBo bo);
-
-    /**
-     * 鏍¢獙骞跺垹闄ゆ暟鎹�
-     *
-     * @param ids     涓婚敭闆嗗悎
-     * @param isValid 鏄惁鏍¢獙,true-鍒犻櫎鍓嶆牎楠�,false-涓嶆牎楠�
-     * @return
-     */
-    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
-
-    /**
-     * 鍚敤鍋滅敤鐘舵��
-     */
-    int updateOssConfigStatus(SysOssConfigBo bo);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
deleted file mode 100644
index 3e15c5f..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.bo.SysOssBo;
-import com.ruoyi.system.domain.vo.SysOssVo;
-import jakarta.servlet.http.HttpServletResponse;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 鏂囦欢涓婁紶 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface ISysOssService {
-
-    TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
-
-    List<SysOssVo> listByIds(Collection<Long> ossIds);
-
-    SysOssVo getById(Long ossId);
-
-    SysOssVo upload(MultipartFile file);
-
-    void download(Long ossId, HttpServletResponse response) throws IOException;
-
-    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
deleted file mode 100644
index 9c3b78c..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysPost;
-
-import java.util.List;
-
-/**
- * 宀椾綅淇℃伅 鏈嶅姟灞�
- *
- * @author Lion Li
- */
-public interface ISysPostService {
-
-
-    TableDataInfo<SysPost> selectPagePostList(SysPost post, PageQuery pageQuery);
-
-    /**
-     * 鏌ヨ宀椾綅淇℃伅闆嗗悎
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 宀椾綅鍒楄〃
-     */
-    List<SysPost> selectPostList(SysPost post);
-
-    /**
-     * 鏌ヨ鎵�鏈夊矖浣�
-     *
-     * @return 宀椾綅鍒楄〃
-     */
-    List<SysPost> selectPostAll();
-
-    /**
-     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
-     *
-     * @param postId 宀椾綅ID
-     * @return 瑙掕壊瀵硅薄淇℃伅
-     */
-    SysPost selectPostById(Long postId);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 閫変腑宀椾綅ID鍒楄〃
-     */
-    List<Long> selectPostListByUserId(Long userId);
-
-    /**
-     * 鏍¢獙宀椾綅鍚嶇О
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    String checkPostNameUnique(SysPost post);
-
-    /**
-     * 鏍¢獙宀椾綅缂栫爜
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    String checkPostCodeUnique(SysPost post);
-
-    /**
-     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
-     *
-     * @param postId 宀椾綅ID
-     * @return 缁撴灉
-     */
-    long countUserPostById(Long postId);
-
-    /**
-     * 鍒犻櫎宀椾綅淇℃伅
-     *
-     * @param postId 宀椾綅ID
-     * @return 缁撴灉
-     */
-    int deletePostById(Long postId);
-
-    /**
-     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
-     *
-     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
-     * @return 缁撴灉
-     */
-    int deletePostByIds(Long[] postIds);
-
-    /**
-     * 鏂板淇濆瓨宀椾綅淇℃伅
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    int insertPost(SysPost post);
-
-    /**
-     * 淇敼淇濆瓨宀椾綅淇℃伅
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    int updatePost(SysPost post);
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
deleted file mode 100644
index b83584d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.system.domain.SysUserRole;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * 瑙掕壊涓氬姟灞�
- *
- * @author Lion Li
- */
-public interface ISysRoleService {
-
-
-    TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
-     */
-    List<SysRole> selectRoleList(SysRole role);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鍒楄〃
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 瑙掕壊鍒楄〃
-     */
-    List<SysRole> selectRolesByUserId(Long userId);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鏉冮檺
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鏉冮檺鍒楄〃
-     */
-    Set<String> selectRolePermissionByUserId(Long userId);
-
-    /**
-     * 鏌ヨ鎵�鏈夎鑹�
-     *
-     * @return 瑙掕壊鍒楄〃
-     */
-    List<SysRole> selectRoleAll();
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 閫変腑瑙掕壊ID鍒楄〃
-     */
-    List<Long> selectRoleListByUserId(Long userId);
-
-    /**
-     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 瑙掕壊瀵硅薄淇℃伅
-     */
-    SysRole selectRoleById(Long roleId);
-
-    /**
-     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    String checkRoleNameUnique(SysRole role);
-
-    /**
-     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    String checkRoleKeyUnique(SysRole role);
-
-    /**
-     * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
-     *
-     * @param role 瑙掕壊淇℃伅
-     */
-    void checkRoleAllowed(SysRole role);
-
-    /**
-     * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
-     *
-     * @param roleId 瑙掕壊id
-     */
-    void checkRoleDataScope(Long roleId);
-
-    /**
-     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 缁撴灉
-     */
-    long countUserRoleByRoleId(Long roleId);
-
-    /**
-     * 鏂板淇濆瓨瑙掕壊淇℃伅
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    int insertRole(SysRole role);
-
-    /**
-     * 淇敼淇濆瓨瑙掕壊淇℃伅
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    int updateRole(SysRole role);
-
-    /**
-     * 淇敼瑙掕壊鐘舵��
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    int updateRoleStatus(SysRole role);
-
-    /**
-     * 淇敼鏁版嵁鏉冮檺淇℃伅
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    int authDataScope(SysRole role);
-
-    /**
-     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 缁撴灉
-     */
-    int deleteRoleById(Long roleId);
-
-    /**
-     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
-     *
-     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
-     * @return 缁撴灉
-     */
-    int deleteRoleByIds(Long[] roleIds);
-
-    /**
-     * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
-     *
-     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
-     * @return 缁撴灉
-     */
-    int deleteAuthUser(SysUserRole userRole);
-
-    /**
-     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
-     *
-     * @param roleId  瑙掕壊ID
-     * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
-     * @return 缁撴灉
-     */
-    int deleteAuthUsers(Long roleId, Long[] userIds);
-
-    /**
-     * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
-     *
-     * @param roleId  瑙掕壊ID
-     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
-     * @return 缁撴灉
-     */
-    int insertAuthUsers(Long roleId, Long[] userIds);
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
deleted file mode 100644
index 8d5a326..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package com.ruoyi.system.service;
-
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.page.TableDataInfo;
-
-import java.util.List;
-
-/**
- * 鐢ㄦ埛 涓氬姟灞�
- *
- * @author Lion Li
- */
-public interface ISysUserService {
-
-
-    TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    List<SysUser> selectUserList(SysUser user);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery);
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery);
-
-    /**
-     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    SysUser selectUserByUserName(String userName);
-
-    /**
-     * 閫氳繃鎵嬫満鍙锋煡璇㈢敤鎴�
-     *
-     * @param phonenumber 鎵嬫満鍙�
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    SysUser selectUserByPhonenumber(String phonenumber);
-
-    /**
-     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    SysUser selectUserById(Long userId);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 缁撴灉
-     */
-    String selectUserRoleGroup(String userName);
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 缁撴灉
-     */
-    String selectUserPostGroup(String userName);
-
-    /**
-     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    String checkUserNameUnique(SysUser user);
-
-    /**
-     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    String checkPhoneUnique(SysUser user);
-
-    /**
-     * 鏍¢獙email鏄惁鍞竴
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    String checkEmailUnique(SysUser user);
-
-    /**
-     * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     */
-    void checkUserAllowed(SysUser user);
-
-    /**
-     * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
-     *
-     * @param userId 鐢ㄦ埛id
-     */
-    void checkUserDataScope(Long userId);
-
-    /**
-     * 鏂板鐢ㄦ埛淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    int insertUser(SysUser user);
-
-    /**
-     * 娉ㄥ唽鐢ㄦ埛淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    boolean registerUser(SysUser user);
-
-    /**
-     * 淇敼鐢ㄦ埛淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    int updateUser(SysUser user);
-
-    /**
-     * 鐢ㄦ埛鎺堟潈瑙掕壊
-     *
-     * @param userId  鐢ㄦ埛ID
-     * @param roleIds 瑙掕壊缁�
-     */
-    void insertUserAuth(Long userId, Long[] roleIds);
-
-    /**
-     * 淇敼鐢ㄦ埛鐘舵��
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    int updateUserStatus(SysUser user);
-
-    /**
-     * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    int updateUserProfile(SysUser user);
-
-    /**
-     * 淇敼鐢ㄦ埛澶村儚
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @param avatar   澶村儚鍦板潃
-     * @return 缁撴灉
-     */
-    boolean updateUserAvatar(String userName, String avatar);
-
-    /**
-     * 閲嶇疆鐢ㄦ埛瀵嗙爜
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    int resetPwd(SysUser user);
-
-    /**
-     * 閲嶇疆鐢ㄦ埛瀵嗙爜
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @param password 瀵嗙爜
-     * @return 缁撴灉
-     */
-    int resetUserPwd(String userName, String password);
-
-    /**
-     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 缁撴灉
-     */
-    int deleteUserById(Long userId);
-
-    /**
-     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
-     *
-     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
-     * @return 缁撴灉
-     */
-    int deleteUserByIds(Long[] userIds);
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
deleted file mode 100644
index 1290c3c..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package com.ruoyi.system.service;
-
-import cn.dev33.satoken.exception.NotLoginException;
-import cn.dev33.satoken.secure.BCrypt;
-import cn.dev33.satoken.stp.StpUtil;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.core.domain.event.LogininforEvent;
-import com.ruoyi.common.core.domain.dto.RoleDTO;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.core.domain.model.XcxLoginUser;
-import com.ruoyi.common.enums.DeviceType;
-import com.ruoyi.common.enums.LoginType;
-import com.ruoyi.common.enums.UserStatus;
-import com.ruoyi.common.exception.user.CaptchaException;
-import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.exception.user.UserException;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.system.mapper.SysUserMapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-
-import jakarta.servlet.http.HttpServletRequest;
-import java.time.Duration;
-import java.util.List;
-import java.util.function.Supplier;
-
-/**
- * 鐧诲綍鏍¢獙鏂规硶
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Slf4j
-@Service
-public class SysLoginService {
-
-    private final SysUserMapper userMapper;
-    private final ISysConfigService configService;
-    private final SysPermissionService permissionService;
-
-    @Value("${user.password.maxRetryCount}")
-    private Integer maxRetryCount;
-
-    @Value("${user.password.lockTime}")
-    private Integer lockTime;
-
-    /**
-     * 鐧诲綍楠岃瘉
-     *
-     * @param username 鐢ㄦ埛鍚�
-     * @param password 瀵嗙爜
-     * @param code     楠岃瘉鐮�
-     * @param uuid     鍞竴鏍囪瘑
-     * @return 缁撴灉
-     */
-    public String login(String username, String password, String code, String uuid) {
-        HttpServletRequest request = ServletUtils.getRequest();
-        boolean captchaEnabled = configService.selectCaptchaEnabled();
-        // 楠岃瘉鐮佸紑鍏�
-        if (captchaEnabled) {
-            validateCaptcha(username, code, uuid, request);
-        }
-        SysUser user = loadUserByUsername(username);
-        checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
-        // 姝ゅ鍙牴鎹櫥褰曠敤鎴风殑鏁版嵁涓嶅悓 鑷鍒涘缓 loginUser
-        LoginUser loginUser = buildLoginUser(user);
-        // 鐢熸垚token
-        LoginHelper.loginByDevice(loginUser, DeviceType.PC);
-
-        recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId(), username);
-        return StpUtil.getTokenValue();
-    }
-
-    public String smsLogin(String phonenumber, String smsCode) {
-        // 閫氳繃鎵嬫満鍙锋煡鎵剧敤鎴�
-        SysUser user = loadUserByPhonenumber(phonenumber);
-
-        checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode));
-        // 姝ゅ鍙牴鎹櫥褰曠敤鎴风殑鏁版嵁涓嶅悓 鑷鍒涘缓 loginUser
-        LoginUser loginUser = buildLoginUser(user);
-        // 鐢熸垚token
-        LoginHelper.loginByDevice(loginUser, DeviceType.APP);
-
-        recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId(), user.getUserName());
-        return StpUtil.getTokenValue();
-    }
-
-
-    public String xcxLogin(String xcxCode) {
-        // xcxCode 涓� 灏忕▼搴忚皟鐢� wx.login 鎺堟潈鍚庤幏鍙�
-        // todo 浠ヤ笅鑷瀹炵幇
-        // 鏍¢獙 appid + appsrcret + xcxCode 璋冪敤鐧诲綍鍑瘉鏍¢獙鎺ュ彛 鑾峰彇 session_key 涓� openid
-        String openid = "";
-        SysUser user = loadUserByOpenid(openid);
-
-        // 姝ゅ鍙牴鎹櫥褰曠敤鎴风殑鏁版嵁涓嶅悓 鑷鍒涘缓 loginUser
-        XcxLoginUser loginUser = new XcxLoginUser();
-        loginUser.setUserId(user.getUserId());
-        loginUser.setUsername(user.getUserName());
-        loginUser.setUserType(user.getUserType());
-        loginUser.setOpenid(openid);
-        // 鐢熸垚token
-        LoginHelper.loginByDevice(loginUser, DeviceType.XCX);
-
-        recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
-        recordLoginInfo(user.getUserId(), user.getUserName());
-        return StpUtil.getTokenValue();
-    }
-
-    /**
-     * 閫�鍑虹櫥褰�
-     */
-    public void logout() {
-        try {
-            LoginUser loginUser = LoginHelper.getLoginUser();
-            StpUtil.logout();
-            recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
-        } catch (NotLoginException ignored) {
-        }
-    }
-
-    /**
-     * 璁板綍鐧诲綍淇℃伅
-     *
-     * @param username 鐢ㄦ埛鍚�
-     * @param status   鐘舵��
-     * @param message  娑堟伅鍐呭
-     * @return
-     */
-    private void recordLogininfor(String username, String status, String message) {
-        LogininforEvent logininforEvent = new LogininforEvent();
-        logininforEvent.setUsername(username);
-        logininforEvent.setStatus(status);
-        logininforEvent.setMessage(message);
-        logininforEvent.setRequest(ServletUtils.getRequest());
-        SpringUtils.context().publishEvent(logininforEvent);
-    }
-
-    /**
-     * 鏍¢獙鐭俊楠岃瘉鐮�
-     */
-    private boolean validateSmsCode(String phonenumber, String smsCode) {
-        String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber);
-        if (StringUtils.isBlank(code)) {
-            recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        return code.equals(smsCode);
-    }
-
-    /**
-     * 鏍¢獙楠岃瘉鐮�
-     *
-     * @param username 鐢ㄦ埛鍚�
-     * @param code     楠岃瘉鐮�
-     * @param uuid     鍞竴鏍囪瘑
-     */
-    public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
-        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
-        String captcha = RedisUtils.getCacheObject(verifyKey);
-        RedisUtils.deleteObject(verifyKey);
-        if (captcha == null) {
-            recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        if (!code.equalsIgnoreCase(captcha)) {
-            recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"));
-            throw new CaptchaException();
-        }
-    }
-
-    private SysUser loadUserByUsername(String username) {
-        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
-            .select(SysUser::getUserName, SysUser::getStatus)
-            .eq(SysUser::getUserName, username));
-        if (ObjectUtil.isNull(user)) {
-            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", username);
-            throw new UserException("user.not.exists", username);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", username);
-            throw new UserException("user.blocked", username);
-        }
-        return userMapper.selectUserByUserName(username);
-    }
-
-    private SysUser loadUserByPhonenumber(String phonenumber) {
-        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
-            .select(SysUser::getPhonenumber, SysUser::getStatus)
-            .eq(SysUser::getPhonenumber, phonenumber));
-        if (ObjectUtil.isNull(user)) {
-            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", phonenumber);
-            throw new UserException("user.not.exists", phonenumber);
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", phonenumber);
-            throw new UserException("user.blocked", phonenumber);
-        }
-        return userMapper.selectUserByPhonenumber(phonenumber);
-    }
-
-    private SysUser loadUserByOpenid(String openid) {
-        // 浣跨敤 openid 鏌ヨ缁戝畾鐢ㄦ埛 濡傛湭缁戝畾鐢ㄦ埛 鍒欐牴鎹笟鍔¤嚜琛屽鐞� 渚嬪 鍒涘缓榛樿鐢ㄦ埛
-        // todo 鑷瀹炵幇 userService.selectUserByOpenid(openid);
-        SysUser user = new SysUser();
-        if (ObjectUtil.isNull(user)) {
-            log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", openid);
-            // todo 鐢ㄦ埛涓嶅瓨鍦� 涓氬姟閫昏緫鑷瀹炵幇
-        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", openid);
-            // todo 鐢ㄦ埛宸茶鍋滅敤 涓氬姟閫昏緫鑷瀹炵幇
-        }
-        return user;
-    }
-
-    /**
-     * 鏋勫缓鐧诲綍鐢ㄦ埛
-     */
-    private LoginUser buildLoginUser(SysUser user) {
-        LoginUser loginUser = new LoginUser();
-        loginUser.setUserId(user.getUserId());
-        loginUser.setDeptId(user.getDeptId());
-        loginUser.setUsername(user.getUserName());
-        loginUser.setUserType(user.getUserType());
-        loginUser.setMenuPermission(permissionService.getMenuPermission(user));
-        loginUser.setRolePermission(permissionService.getRolePermission(user));
-        loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName());
-        List<RoleDTO> roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class);
-        loginUser.setRoles(roles);
-        return loginUser;
-    }
-
-    /**
-     * 璁板綍鐧诲綍淇℃伅
-     *
-     * @param userId 鐢ㄦ埛ID
-     */
-    public void recordLoginInfo(Long userId, String username) {
-        SysUser sysUser = new SysUser();
-        sysUser.setUserId(userId);
-        sysUser.setLoginIp(ServletUtils.getClientIP());
-        sysUser.setLoginDate(DateUtils.getNowDate());
-        sysUser.setUpdateBy(username);
-        userMapper.updateById(sysUser);
-    }
-
-    /**
-     * 鐧诲綍鏍¢獙
-     */
-    private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
-        String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username;
-        String loginFail = Constants.LOGIN_FAIL;
-
-        // 鑾峰彇鐢ㄦ埛鐧诲綍閿欒娆℃暟(鍙嚜瀹氫箟闄愬埗绛栫暐 渚嬪: key + username + ip)
-        Integer errorNumber = RedisUtils.getCacheObject(errorKey);
-        // 閿佸畾鏃堕棿鍐呯櫥褰� 鍒欒涪鍑�
-        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
-            recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
-            throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
-        }
-
-        if (supplier.get()) {
-            // 鏄惁绗竴娆�
-            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
-            // 杈惧埌瑙勫畾閿欒娆℃暟 鍒欓攣瀹氱櫥褰�
-            if (errorNumber.equals(maxRetryCount)) {
-                RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
-                recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
-                throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
-            } else {
-                // 鏈揪鍒拌瀹氶敊璇鏁� 鍒欓�掑
-                RedisUtils.setCacheObject(errorKey, errorNumber);
-                recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
-                throw new UserException(loginType.getRetryLimitCount(), errorNumber);
-            }
-        }
-
-        // 鐧诲綍鎴愬姛 娓呯┖閿欒娆℃暟
-        RedisUtils.deleteObject(errorKey);
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java
deleted file mode 100644
index bd46055..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.system.service;
-
-import cn.dev33.satoken.secure.BCrypt;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.event.LogininforEvent;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.domain.model.RegisterBody;
-import com.ruoyi.common.enums.UserType;
-import com.ruoyi.common.exception.user.CaptchaException;
-import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.exception.user.UserException;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import jakarta.servlet.http.HttpServletRequest;
-
-/**
- * 娉ㄥ唽鏍¢獙鏂规硶
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysRegisterService {
-
-    private final ISysUserService userService;
-    private final ISysConfigService configService;
-
-    /**
-     * 娉ㄥ唽
-     */
-    public void register(RegisterBody registerBody) {
-        HttpServletRequest request = ServletUtils.getRequest();
-        String username = registerBody.getUsername();
-        String password = registerBody.getPassword();
-        // 鏍¢獙鐢ㄦ埛绫诲瀷鏄惁瀛樺湪
-        String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
-
-        boolean captchaEnabled = configService.selectCaptchaEnabled();
-        // 楠岃瘉鐮佸紑鍏�
-        if (captchaEnabled) {
-            validateCaptcha(username, registerBody.getCode(), registerBody.getUuid(), request);
-        }
-        SysUser sysUser = new SysUser();
-        sysUser.setUserName(username);
-        sysUser.setNickName(username);
-        sysUser.setPassword(BCrypt.hashpw(password));
-        sysUser.setUserType(userType);
-
-        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) {
-            throw new UserException("user.register.save.error", username);
-        }
-        boolean regFlag = userService.registerUser(sysUser);
-        if (!regFlag) {
-            throw new UserException("user.register.error");
-        }
-        recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"));
-    }
-
-    /**
-     * 鏍¢獙楠岃瘉鐮�
-     *
-     * @param username 鐢ㄦ埛鍚�
-     * @param code     楠岃瘉鐮�
-     * @param uuid     鍞竴鏍囪瘑
-     * @return 缁撴灉
-     */
-    public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
-        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
-        String captcha = RedisUtils.getCacheObject(verifyKey);
-        RedisUtils.deleteObject(verifyKey);
-        if (captcha == null) {
-            recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.expire"));
-            throw new CaptchaExpireException();
-        }
-        if (!code.equalsIgnoreCase(captcha)) {
-            recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.jcaptcha.error"));
-            throw new CaptchaException();
-        }
-    }
-
-    /**
-     * 璁板綍鐧诲綍淇℃伅
-     *
-     * @param username 鐢ㄦ埛鍚�
-     * @param status   鐘舵��
-     * @param message  娑堟伅鍐呭
-     * @return
-     */
-    private void recordLogininfor(String username, String status, String message) {
-        LogininforEvent logininforEvent = new LogininforEvent();
-        logininforEvent.setUsername(username);
-        logininforEvent.setStatus(status);
-        logininforEvent.setMessage(message);
-        logininforEvent.setRequest(ServletUtils.getRequest());
-        SpringUtils.context().publishEvent(logininforEvent);
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
deleted file mode 100644
index c39ec74..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.service.ConfigService;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.system.domain.SysConfig;
-import com.ruoyi.system.mapper.SysConfigMapper;
-import com.ruoyi.system.service.ISysConfigService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.stereotype.Service;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鍙傛暟閰嶇疆 鏈嶅姟灞傚疄鐜�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
-
-    private final SysConfigMapper baseMapper;
-
-    @Override
-    public TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery) {
-        Map<String, Object> params = config.getParams();
-        LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
-            .like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
-            .eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
-            .like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
-        Page<SysConfig> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
-     *
-     * @param configId 鍙傛暟閰嶇疆ID
-     * @return 鍙傛暟閰嶇疆淇℃伅
-     */
-    @Override
-    @DS("master")
-    public SysConfig selectConfigById(Long configId) {
-        return baseMapper.selectById(configId);
-    }
-
-    /**
-     * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
-     *
-     * @param configKey 鍙傛暟key
-     * @return 鍙傛暟閿��
-     */
-    @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey")
-    @Override
-    public String selectConfigByKey(String configKey) {
-        SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
-            .eq(SysConfig::getConfigKey, configKey));
-        if (ObjectUtil.isNotNull(retConfig)) {
-            return retConfig.getConfigValue();
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 鑾峰彇楠岃瘉鐮佸紑鍏�
-     *
-     * @return true寮�鍚紝false鍏抽棴
-     */
-    @Override
-    public boolean selectCaptchaEnabled() {
-        String captchaEnabled = SpringUtils.getAopProxy(this).selectConfigByKey("sys.account.captchaEnabled");
-        if (StringUtils.isEmpty(captchaEnabled)) {
-            return true;
-        }
-        return Convert.toBool(captchaEnabled);
-    }
-
-    /**
-     * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 鍙傛暟閰嶇疆闆嗗悎
-     */
-    @Override
-    public List<SysConfig> selectConfigList(SysConfig config) {
-        Map<String, Object> params = config.getParams();
-        LambdaQueryWrapper<SysConfig> lqw = new LambdaQueryWrapper<SysConfig>()
-            .like(StringUtils.isNotBlank(config.getConfigName()), SysConfig::getConfigName, config.getConfigName())
-            .eq(StringUtils.isNotBlank(config.getConfigType()), SysConfig::getConfigType, config.getConfigType())
-            .like(StringUtils.isNotBlank(config.getConfigKey()), SysConfig::getConfigKey, config.getConfigKey())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
-        return baseMapper.selectList(lqw);
-    }
-
-    /**
-     * 鏂板鍙傛暟閰嶇疆
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 缁撴灉
-     */
-    @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey")
-    @Override
-    public String insertConfig(SysConfig config) {
-        int row = baseMapper.insert(config);
-        if (row > 0) {
-            return config.getConfigValue();
-        }
-        throw new ServiceException("鎿嶄綔澶辫触");
-    }
-
-    /**
-     * 淇敼鍙傛暟閰嶇疆
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 缁撴灉
-     */
-    @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey")
-    @Override
-    public String updateConfig(SysConfig config) {
-        int row = 0;
-        if (config.getConfigId() != null) {
-            SysConfig temp = baseMapper.selectById(config.getConfigId());
-            if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
-                CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey());
-            }
-            row = baseMapper.updateById(config);
-        } else {
-            row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
-                .eq(SysConfig::getConfigKey, config.getConfigKey()));
-        }
-        if (row > 0) {
-            return config.getConfigValue();
-        }
-        throw new ServiceException("鎿嶄綔澶辫触");
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
-     *
-     * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
-     */
-    @Override
-    public void deleteConfigByIds(Long[] configIds) {
-        for (Long configId : configIds) {
-            SysConfig config = selectConfigById(configId);
-            if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
-                throw new ServiceException(String.format("鍐呯疆鍙傛暟銆�%1$s銆戜笉鑳藉垹闄� ", config.getConfigKey()));
-            }
-            CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
-        }
-        baseMapper.deleteBatchIds(Arrays.asList(configIds));
-    }
-
-    /**
-     * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
-     */
-    @Override
-    public void loadingConfigCache() {
-        List<SysConfig> configsList = selectConfigList(new SysConfig());
-        configsList.forEach(config ->
-            CacheUtils.put(CacheNames.SYS_CONFIG, config.getConfigKey(), config.getConfigValue()));
-    }
-
-    /**
-     * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
-     */
-    @Override
-    public void clearConfigCache() {
-        CacheUtils.clear(CacheNames.SYS_CONFIG);
-    }
-
-    /**
-     * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
-     */
-    @Override
-    public void resetConfigCache() {
-        clearConfigCache();
-        loadingConfigCache();
-    }
-
-    /**
-     * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
-     *
-     * @param config 鍙傛暟閰嶇疆淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkConfigKeyUnique(SysConfig config) {
-        Long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId();
-        SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey()));
-        if (ObjectUtil.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍规嵁鍙傛暟 key 鑾峰彇鍙傛暟鍊�
-     *
-     * @param configKey 鍙傛暟 key
-     * @return 鍙傛暟鍊�
-     */
-    @Override
-    public String getConfigValue(String configKey) {
-        return SpringUtils.getAopProxy(this).selectConfigByKey(configKey);
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java
deleted file mode 100644
index 9c01c7a..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.convert.Convert;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.common.helper.DataBaseHelper;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.system.domain.SysRoleDept;
-import com.ruoyi.system.mapper.SysDeptMapper;
-import com.ruoyi.system.mapper.SysRoleDeptMapper;
-import com.ruoyi.system.service.ISysDataScopeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * 鏁版嵁鏉冮檺 瀹炵幇
- * <p>
- * 娉ㄦ剰: 姝ervice鍐呬笉鍏佽璋冪敤鏍囨敞`鏁版嵁鏉冮檺`娉ㄨВ鐨勬柟娉�
- * 渚嬪: deptMapper.selectList 姝� selectList 鏂规硶鏍囨敞浜哷鏁版嵁鏉冮檺`娉ㄨВ 浼氬嚭鐜板惊鐜В鏋愮殑闂
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service("sdss")
-public class SysDataScopeServiceImpl implements ISysDataScopeService {
-
-    private final SysRoleDeptMapper roleDeptMapper;
-    private final SysDeptMapper deptMapper;
-
-    @Override
-    public String getRoleCustom(Long roleId) {
-        List<SysRoleDept> list = roleDeptMapper.selectList(
-            new LambdaQueryWrapper<SysRoleDept>()
-                .select(SysRoleDept::getDeptId)
-                .eq(SysRoleDept::getRoleId, roleId));
-        if (CollUtil.isNotEmpty(list)) {
-            return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId()));
-        }
-        return null;
-    }
-
-    @Override
-    public String getDeptAndChild(Long deptId) {
-        List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
-            .select(SysDept::getDeptId)
-            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
-        List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
-        ids.add(deptId);
-        List<SysDept> list = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
-            .select(SysDept::getDeptId)
-            .in(SysDept::getDeptId, ids));
-        if (CollUtil.isNotEmpty(list)) {
-            return StreamUtils.join(list, d -> Convert.toStr(d.getDeptId()));
-        }
-        return null;
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
deleted file mode 100644
index 6067a7d..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.lang.tree.Tree;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.DataBaseHelper;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.TreeBuildUtils;
-import com.ruoyi.system.mapper.SysDeptMapper;
-import com.ruoyi.system.mapper.SysRoleMapper;
-import com.ruoyi.system.mapper.SysUserMapper;
-import com.ruoyi.system.service.ISysDeptService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 閮ㄩ棬绠$悊 鏈嶅姟瀹炵幇
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysDeptServiceImpl implements ISysDeptService {
-
-    private final SysDeptMapper baseMapper;
-    private final SysRoleMapper roleMapper;
-    private final SysUserMapper userMapper;
-
-    /**
-     * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
-     *
-     * @param dept 閮ㄩ棬淇℃伅
-     * @return 閮ㄩ棬淇℃伅闆嗗悎
-     */
-    @Override
-    public List<SysDept> selectDeptList(SysDept dept) {
-        LambdaQueryWrapper<SysDept> lqw = new LambdaQueryWrapper<>();
-        lqw.eq(SysDept::getDelFlag, "0")
-            .eq(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())
-            .eq(ObjectUtil.isNotNull(dept.getParentId()), SysDept::getParentId, dept.getParentId())
-            .like(StringUtils.isNotBlank(dept.getDeptName()), SysDept::getDeptName, dept.getDeptName())
-            .eq(StringUtils.isNotBlank(dept.getStatus()), SysDept::getStatus, dept.getStatus())
-            .orderByAsc(SysDept::getParentId)
-            .orderByAsc(SysDept::getOrderNum);
-        return baseMapper.selectDeptList(lqw);
-    }
-
-    /**
-     * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
-     *
-     * @param dept 閮ㄩ棬淇℃伅
-     * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
-     */
-    @Override
-    public List<Tree<Long>> selectDeptTreeList(SysDept dept) {
-        List<SysDept> depts = this.selectDeptList(dept);
-        return buildDeptTreeSelect(depts);
-    }
-
-    /**
-     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
-     *
-     * @param depts 閮ㄩ棬鍒楄〃
-     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
-     */
-    @Override
-    public List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts) {
-        if (CollUtil.isEmpty(depts)) {
-            return CollUtil.newArrayList();
-        }
-        return TreeBuildUtils.build(depts, (dept, tree) ->
-            tree.setId(dept.getDeptId())
-                .setParentId(dept.getParentId())
-                .setName(dept.getDeptName())
-                .setWeight(dept.getOrderNum()));
-    }
-
-    /**
-     * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 閫変腑閮ㄩ棬鍒楄〃
-     */
-    @Override
-    public List<Long> selectDeptListByRoleId(Long roleId) {
-        SysRole role = roleMapper.selectById(roleId);
-        return baseMapper.selectDeptListByRoleId(roleId, role.getDeptCheckStrictly());
-    }
-
-    /**
-     * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
-     *
-     * @param deptId 閮ㄩ棬ID
-     * @return 閮ㄩ棬淇℃伅
-     */
-    @Override
-    public SysDept selectDeptById(Long deptId) {
-        SysDept dept = baseMapper.selectById(deptId);
-        SysDept parentDept = baseMapper.selectOne(new LambdaQueryWrapper<SysDept>()
-            .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId()));
-        dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null);
-        return dept;
-    }
-
-    /**
-     * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬鏁帮紙姝e父鐘舵�侊級
-     *
-     * @param deptId 閮ㄩ棬ID
-     * @return 瀛愰儴闂ㄦ暟
-     */
-    @Override
-    public long selectNormalChildrenDeptById(Long deptId) {
-        return baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
-            .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
-            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
-    }
-
-    /**
-     * 鏄惁瀛樺湪瀛愯妭鐐�
-     *
-     * @param deptId 閮ㄩ棬ID
-     * @return 缁撴灉
-     */
-    @Override
-    public boolean hasChildByDeptId(Long deptId) {
-        return baseMapper.exists(new LambdaQueryWrapper<SysDept>()
-            .eq(SysDept::getParentId, deptId));
-    }
-
-    /**
-     * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
-     *
-     * @param deptId 閮ㄩ棬ID
-     * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
-     */
-    @Override
-    public boolean checkDeptExistUser(Long deptId) {
-        return userMapper.exists(new LambdaQueryWrapper<SysUser>()
-            .eq(SysUser::getDeptId, deptId));
-    }
-
-    /**
-     * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
-     *
-     * @param dept 閮ㄩ棬淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkDeptNameUnique(SysDept dept) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDept>()
-            .eq(SysDept::getDeptName, dept.getDeptName())
-            .eq(SysDept::getParentId, dept.getParentId())
-            .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙閮ㄩ棬鏄惁鏈夋暟鎹潈闄�
-     *
-     * @param deptId 閮ㄩ棬id
-     */
-    @Override
-    public void checkDeptDataScope(Long deptId) {
-        if (!LoginHelper.isAdmin()) {
-            SysDept dept = new SysDept();
-            dept.setDeptId(deptId);
-            List<SysDept> depts = this.selectDeptList(dept);
-            if (CollUtil.isEmpty(depts)) {
-                throw new ServiceException("娌℃湁鏉冮檺璁块棶閮ㄩ棬鏁版嵁锛�");
-            }
-        }
-    }
-
-    /**
-     * 鏂板淇濆瓨閮ㄩ棬淇℃伅
-     *
-     * @param dept 閮ㄩ棬淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int insertDept(SysDept dept) {
-        SysDept info = baseMapper.selectById(dept.getParentId());
-        // 濡傛灉鐖惰妭鐐逛笉涓烘甯哥姸鎬�,鍒欎笉鍏佽鏂板瀛愯妭鐐�
-        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
-            throw new ServiceException("閮ㄩ棬鍋滅敤锛屼笉鍏佽鏂板");
-        }
-        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
-        return baseMapper.insert(dept);
-    }
-
-    /**
-     * 淇敼淇濆瓨閮ㄩ棬淇℃伅
-     *
-     * @param dept 閮ㄩ棬淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updateDept(SysDept dept) {
-        SysDept newParentDept = baseMapper.selectById(dept.getParentId());
-        SysDept oldDept = baseMapper.selectById(dept.getDeptId());
-        if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) {
-            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
-            String oldAncestors = oldDept.getAncestors();
-            dept.setAncestors(newAncestors);
-            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
-        }
-        int result = baseMapper.updateById(dept);
-        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
-            && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) {
-            // 濡傛灉璇ラ儴闂ㄦ槸鍚敤鐘舵�侊紝鍒欏惎鐢ㄨ閮ㄩ棬鐨勬墍鏈変笂绾ч儴闂�
-            updateParentDeptStatusNormal(dept);
-        }
-        return result;
-    }
-
-    /**
-     * 淇敼璇ラ儴闂ㄧ殑鐖剁骇閮ㄩ棬鐘舵��
-     *
-     * @param dept 褰撳墠閮ㄩ棬
-     */
-    private void updateParentDeptStatusNormal(SysDept dept) {
-        String ancestors = dept.getAncestors();
-        Long[] deptIds = Convert.toLongArray(ancestors);
-        baseMapper.update(null, new LambdaUpdateWrapper<SysDept>()
-            .set(SysDept::getStatus, UserConstants.DEPT_NORMAL)
-            .in(SysDept::getDeptId, Arrays.asList(deptIds)));
-    }
-
-    /**
-     * 淇敼瀛愬厓绱犲叧绯�
-     *
-     * @param deptId       琚慨鏀圭殑閮ㄩ棬ID
-     * @param newAncestors 鏂扮殑鐖禝D闆嗗悎
-     * @param oldAncestors 鏃х殑鐖禝D闆嗗悎
-     */
-    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
-        List<SysDept> children = baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
-            .apply(DataBaseHelper.findInSet(deptId, "ancestors")));
-        List<SysDept> list = new ArrayList<>();
-        for (SysDept child : children) {
-            SysDept dept = new SysDept();
-            dept.setDeptId(child.getDeptId());
-            dept.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
-            list.add(dept);
-        }
-        if (list.size() > 0) {
-            baseMapper.updateBatchById(list);
-        }
-    }
-
-    /**
-     * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
-     *
-     * @param deptId 閮ㄩ棬ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteDeptById(Long deptId) {
-        return baseMapper.deleteById(deptId);
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
deleted file mode 100644
index 46fed61..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysDictData;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
-import com.ruoyi.system.mapper.SysDictDataMapper;
-import com.ruoyi.system.service.ISysDictDataService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * 瀛楀吀 涓氬姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysDictDataServiceImpl implements ISysDictDataService {
-
-    private final SysDictDataMapper baseMapper;
-
-    @Override
-    public TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData, PageQuery pageQuery) {
-        LambdaQueryWrapper<SysDictData> lqw = new LambdaQueryWrapper<SysDictData>()
-            .eq(StringUtils.isNotBlank(dictData.getDictType()), SysDictData::getDictType, dictData.getDictType())
-            .like(StringUtils.isNotBlank(dictData.getDictLabel()), SysDictData::getDictLabel, dictData.getDictLabel())
-            .eq(StringUtils.isNotBlank(dictData.getStatus()), SysDictData::getStatus, dictData.getStatus())
-            .orderByAsc(SysDictData::getDictSort);
-        Page<SysDictData> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
-     *
-     * @param dictData 瀛楀吀鏁版嵁淇℃伅
-     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
-     */
-    @Override
-    public List<SysDictData> selectDictDataList(SysDictData dictData) {
-        return baseMapper.selectList(new LambdaQueryWrapper<SysDictData>()
-            .eq(StringUtils.isNotBlank(dictData.getDictType()), SysDictData::getDictType, dictData.getDictType())
-            .like(StringUtils.isNotBlank(dictData.getDictLabel()), SysDictData::getDictLabel, dictData.getDictLabel())
-            .eq(StringUtils.isNotBlank(dictData.getStatus()), SysDictData::getStatus, dictData.getStatus())
-            .orderByAsc(SysDictData::getDictSort));
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictValue 瀛楀吀閿��
-     * @return 瀛楀吀鏍囩
-     */
-    @Override
-    public String selectDictLabel(String dictType, String dictValue) {
-        return baseMapper.selectOne(new LambdaQueryWrapper<SysDictData>()
-                .select(SysDictData::getDictLabel)
-                .eq(SysDictData::getDictType, dictType)
-                .eq(SysDictData::getDictValue, dictValue))
-            .getDictLabel();
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
-     *
-     * @param dictCode 瀛楀吀鏁版嵁ID
-     * @return 瀛楀吀鏁版嵁
-     */
-    @Override
-    public SysDictData selectDictDataById(Long dictCode) {
-        return baseMapper.selectById(dictCode);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
-     */
-    @Override
-    public void deleteDictDataByIds(Long[] dictCodes) {
-        for (Long dictCode : dictCodes) {
-            SysDictData data = selectDictDataById(dictCode);
-            baseMapper.deleteById(dictCode);
-            CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType());
-        }
-    }
-
-    /**
-     * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param data 瀛楀吀鏁版嵁淇℃伅
-     * @return 缁撴灉
-     */
-    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType")
-    @Override
-    public List<SysDictData> insertDictData(SysDictData data) {
-        int row = baseMapper.insert(data);
-        if (row > 0) {
-            return baseMapper.selectDictDataByType(data.getDictType());
-        }
-        throw new ServiceException("鎿嶄綔澶辫触");
-    }
-
-    /**
-     * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
-     *
-     * @param data 瀛楀吀鏁版嵁淇℃伅
-     * @return 缁撴灉
-     */
-    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType")
-    @Override
-    public List<SysDictData> updateDictData(SysDictData data) {
-        int row = baseMapper.updateById(data);
-        if (row > 0) {
-            return baseMapper.selectDictDataByType(data.getDictType());
-        }
-        throw new ServiceException("鎿嶄綔澶辫触");
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
deleted file mode 100644
index bb3ebd7..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
+++ /dev/null
@@ -1,285 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.dev33.satoken.context.SaHolder;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysDictData;
-import com.ruoyi.system.domain.SysDictType;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.service.DictService;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.system.mapper.SysDictDataMapper;
-import com.ruoyi.system.mapper.SysDictTypeMapper;
-import com.ruoyi.system.service.ISysDictTypeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 瀛楀吀 涓氬姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService {
-
-    private final SysDictTypeMapper baseMapper;
-    private final SysDictDataMapper dictDataMapper;
-
-    @Override
-    public TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery) {
-        Map<String, Object> params = dictType.getParams();
-        LambdaQueryWrapper<SysDictType> lqw = new LambdaQueryWrapper<SysDictType>()
-            .like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
-            .eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
-            .like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime"));
-        Page<SysDictType> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
-     *
-     * @param dictType 瀛楀吀绫诲瀷淇℃伅
-     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
-     */
-    @Override
-    public List<SysDictType> selectDictTypeList(SysDictType dictType) {
-        Map<String, Object> params = dictType.getParams();
-        return baseMapper.selectList(new LambdaQueryWrapper<SysDictType>()
-            .like(StringUtils.isNotBlank(dictType.getDictName()), SysDictType::getDictName, dictType.getDictName())
-            .eq(StringUtils.isNotBlank(dictType.getStatus()), SysDictType::getStatus, dictType.getStatus())
-            .like(StringUtils.isNotBlank(dictType.getDictType()), SysDictType::getDictType, dictType.getDictType())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysDictType::getCreateTime, params.get("beginTime"), params.get("endTime")));
-    }
-
-    /**
-     * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
-     *
-     * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
-     */
-    @Override
-    public List<SysDictType> selectDictTypeAll() {
-        return baseMapper.selectList();
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
-     *
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
-     */
-    @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
-    @Override
-    public List<SysDictData> selectDictDataByType(String dictType) {
-        List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType);
-        if (CollUtil.isNotEmpty(dictDatas)) {
-            return dictDatas;
-        }
-        return null;
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
-     *
-     * @param dictId 瀛楀吀绫诲瀷ID
-     * @return 瀛楀吀绫诲瀷
-     */
-    @Override
-    public SysDictType selectDictTypeById(Long dictId) {
-        return baseMapper.selectById(dictId);
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
-     *
-     * @param dictType 瀛楀吀绫诲瀷
-     * @return 瀛楀吀绫诲瀷
-     */
-    @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType")
-    @Override
-    public SysDictType selectDictTypeByType(String dictType) {
-        return baseMapper.selectById(new LambdaQueryWrapper<SysDictType>().eq(SysDictType::getDictType, dictType));
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
-     *
-     * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
-     */
-    @Override
-    public void deleteDictTypeByIds(Long[] dictIds) {
-        for (Long dictId : dictIds) {
-            SysDictType dictType = selectDictTypeById(dictId);
-            if (dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
-                .eq(SysDictData::getDictType, dictType.getDictType()))) {
-                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", dictType.getDictName()));
-            }
-            CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType());
-        }
-        baseMapper.deleteBatchIds(Arrays.asList(dictIds));
-    }
-
-    /**
-     * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
-     */
-    @Override
-    public void loadingDictCache() {
-        List<SysDictData> dictDataList = dictDataMapper.selectList(
-            new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getStatus, UserConstants.DICT_NORMAL));
-        Map<String, List<SysDictData>> dictDataMap = StreamUtils.groupByKey(dictDataList, SysDictData::getDictType);
-        dictDataMap.forEach((k,v) -> {
-            List<SysDictData> dictList = StreamUtils.sorted(v, Comparator.comparing(SysDictData::getDictSort));
-            CacheUtils.put(CacheNames.SYS_DICT, k, dictList);
-        });
-    }
-
-    /**
-     * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
-     */
-    @Override
-    public void clearDictCache() {
-        CacheUtils.clear(CacheNames.SYS_DICT);
-    }
-
-    /**
-     * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
-     */
-    @Override
-    public void resetDictCache() {
-        clearDictCache();
-        loadingDictCache();
-    }
-
-    /**
-     * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
-     *
-     * @param dict 瀛楀吀绫诲瀷淇℃伅
-     * @return 缁撴灉
-     */
-    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType")
-    @Override
-    public List<SysDictData> insertDictType(SysDictType dict) {
-        int row = baseMapper.insert(dict);
-        if (row > 0) {
-            return new ArrayList<>();
-        }
-        throw new ServiceException("鎿嶄綔澶辫触");
-    }
-
-    /**
-     * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
-     *
-     * @param dict 瀛楀吀绫诲瀷淇℃伅
-     * @return 缁撴灉
-     */
-    @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType")
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public List<SysDictData> updateDictType(SysDictType dict) {
-        SysDictType oldDict = baseMapper.selectById(dict.getDictId());
-        dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>()
-            .set(SysDictData::getDictType, dict.getDictType())
-            .eq(SysDictData::getDictType, oldDict.getDictType()));
-        int row = baseMapper.updateById(dict);
-        if (row > 0) {
-            CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType());
-            return dictDataMapper.selectDictDataByType(dict.getDictType());
-        }
-        throw new ServiceException("鎿嶄綔澶辫触");
-    }
-
-    /**
-     * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
-     *
-     * @param dict 瀛楀吀绫诲瀷
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkDictTypeUnique(SysDictType dict) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDictType>()
-            .eq(SysDictType::getDictType, dict.getDictType())
-            .ne(ObjectUtil.isNotNull(dict.getDictId()), SysDictType::getDictId, dict.getDictId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictValue 瀛楀吀鍊�
-     * @param separator 鍒嗛殧绗�
-     * @return 瀛楀吀鏍囩
-     */
-    @SuppressWarnings("unchecked cast")
-    @Override
-    public String getDictLabel(String dictType, String dictValue, String separator) {
-        // 浼樺厛浠庢湰鍦扮紦瀛樿幏鍙�
-        List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
-        if (ObjectUtil.isNull(datas)) {
-            datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
-            SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
-        }
-
-        Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictValue, SysDictData::getDictLabel);
-        if (StringUtils.containsAny(dictValue, separator)) {
-            return Arrays.stream(dictValue.split(separator))
-                .map(v -> map.getOrDefault(v, StringUtils.EMPTY))
-                .collect(Collectors.joining(separator));
-        } else {
-            return map.getOrDefault(dictValue, StringUtils.EMPTY);
-        }
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictLabel 瀛楀吀鏍囩
-     * @param separator 鍒嗛殧绗�
-     * @return 瀛楀吀鍊�
-     */
-    @SuppressWarnings("unchecked cast")
-    @Override
-    public String getDictValue(String dictType, String dictLabel, String separator) {
-        // 浼樺厛浠庢湰鍦扮紦瀛樿幏鍙�
-        List<SysDictData> datas = (List<SysDictData>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
-        if (ObjectUtil.isNull(datas)) {
-            datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
-            SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
-        }
-
-        Map<String, String> map = StreamUtils.toMap(datas, SysDictData::getDictLabel, SysDictData::getDictValue);
-        if (StringUtils.containsAny(dictLabel, separator)) {
-            return Arrays.stream(dictLabel.split(separator))
-                .map(l -> map.getOrDefault(l, StringUtils.EMPTY))
-                .collect(Collectors.joining(separator));
-        } else {
-            return map.getOrDefault(dictLabel, StringUtils.EMPTY);
-        }
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
deleted file mode 100644
index 09d4452..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.http.useragent.UserAgent;
-import cn.hutool.http.useragent.UserAgentUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.event.LogininforEvent;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.ip.AddressUtils;
-import com.ruoyi.system.domain.SysLogininfor;
-import com.ruoyi.system.mapper.SysLogininforMapper;
-import com.ruoyi.system.service.ISysLogininforService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.event.EventListener;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-
-import jakarta.servlet.http.HttpServletRequest;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Slf4j
-@Service
-public class SysLogininforServiceImpl implements ISysLogininforService {
-
-    private final SysLogininforMapper baseMapper;
-
-    /**
-     * 璁板綍鐧诲綍淇℃伅
-     *
-     * @param logininforEvent 鐧诲綍浜嬩欢
-     */
-    @Async
-    @EventListener
-    public void recordLogininfor(LogininforEvent logininforEvent) {
-        HttpServletRequest request = logininforEvent.getRequest();
-        final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
-        final String ip = ServletUtils.getClientIP(request);
-
-        String address = AddressUtils.getRealAddressByIP(ip);
-        StringBuilder s = new StringBuilder();
-        s.append(getBlock(ip));
-        s.append(address);
-        s.append(getBlock(logininforEvent.getUsername()));
-        s.append(getBlock(logininforEvent.getStatus()));
-        s.append(getBlock(logininforEvent.getMessage()));
-        // 鎵撳嵃淇℃伅鍒版棩蹇�
-        log.info(s.toString(), logininforEvent.getArgs());
-        // 鑾峰彇瀹㈡埛绔搷浣滅郴缁�
-        String os = userAgent.getOs().getName();
-        // 鑾峰彇瀹㈡埛绔祻瑙堝櫒
-        String browser = userAgent.getBrowser().getName();
-        // 灏佽瀵硅薄
-        SysLogininfor logininfor = new SysLogininfor();
-        logininfor.setUserName(logininforEvent.getUsername());
-        logininfor.setIpaddr(ip);
-        logininfor.setLoginLocation(address);
-        logininfor.setBrowser(browser);
-        logininfor.setOs(os);
-        logininfor.setMsg(logininforEvent.getMessage());
-        // 鏃ュ織鐘舵��
-        if (StringUtils.equalsAny(logininforEvent.getStatus(), Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
-            logininfor.setStatus(Constants.SUCCESS);
-        } else if (Constants.LOGIN_FAIL.equals(logininforEvent.getStatus())) {
-            logininfor.setStatus(Constants.FAIL);
-        }
-        // 鎻掑叆鏁版嵁
-        insertLogininfor(logininfor);
-    }
-
-    private String getBlock(Object msg) {
-        if (msg == null) {
-            msg = "";
-        }
-        return "[" + msg.toString() + "]";
-    }
-
-    @Override
-    public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery) {
-        Map<String, Object> params = logininfor.getParams();
-        LambdaQueryWrapper<SysLogininfor> lqw = new LambdaQueryWrapper<SysLogininfor>()
-            .like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
-            .eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
-            .like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"));
-        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
-            pageQuery.setOrderByColumn("info_id");
-            pageQuery.setIsAsc("desc");
-        }
-        Page<SysLogininfor> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏂板绯荤粺鐧诲綍鏃ュ織
-     *
-     * @param logininfor 璁块棶鏃ュ織瀵硅薄
-     */
-    @Override
-    public void insertLogininfor(SysLogininfor logininfor) {
-        logininfor.setLoginTime(new Date());
-        baseMapper.insert(logininfor);
-    }
-
-    /**
-     * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
-     *
-     * @param logininfor 璁块棶鏃ュ織瀵硅薄
-     * @return 鐧诲綍璁板綍闆嗗悎
-     */
-    @Override
-    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor) {
-        Map<String, Object> params = logininfor.getParams();
-        return baseMapper.selectList(new LambdaQueryWrapper<SysLogininfor>()
-            .like(StringUtils.isNotBlank(logininfor.getIpaddr()), SysLogininfor::getIpaddr, logininfor.getIpaddr())
-            .eq(StringUtils.isNotBlank(logininfor.getStatus()), SysLogininfor::getStatus, logininfor.getStatus())
-            .like(StringUtils.isNotBlank(logininfor.getUserName()), SysLogininfor::getUserName, logininfor.getUserName())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysLogininfor::getLoginTime, params.get("beginTime"), params.get("endTime"))
-            .orderByDesc(SysLogininfor::getInfoId));
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
-     *
-     * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteLogininforByIds(Long[] infoIds) {
-        return baseMapper.deleteBatchIds(Arrays.asList(infoIds));
-    }
-
-    /**
-     * 娓呯┖绯荤粺鐧诲綍鏃ュ織
-     */
-    @Override
-    public void cleanLogininfor() {
-        baseMapper.delete(new LambdaQueryWrapper<>());
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
deleted file mode 100644
index bc1b430..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
+++ /dev/null
@@ -1,446 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.tree.Tree;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.system.domain.SysMenu;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.TreeBuildUtils;
-import com.ruoyi.system.domain.SysRoleMenu;
-import com.ruoyi.system.domain.vo.MetaVo;
-import com.ruoyi.system.domain.vo.RouterVo;
-import com.ruoyi.system.mapper.SysMenuMapper;
-import com.ruoyi.system.mapper.SysRoleMapper;
-import com.ruoyi.system.mapper.SysRoleMenuMapper;
-import com.ruoyi.system.service.ISysMenuService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.*;
-
-/**
- * 鑿滃崟 涓氬姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysMenuServiceImpl implements ISysMenuService {
-
-    private final SysMenuMapper baseMapper;
-    private final SysRoleMapper roleMapper;
-    private final SysRoleMenuMapper roleMenuMapper;
-
-    /**
-     * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鑿滃崟鍒楄〃
-     */
-    @Override
-    public List<SysMenu> selectMenuList(Long userId) {
-        return selectMenuList(new SysMenu(), userId);
-    }
-
-    /**
-     * 鏌ヨ绯荤粺鑿滃崟鍒楄〃
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 鑿滃崟鍒楄〃
-     */
-    @Override
-    public List<SysMenu> selectMenuList(SysMenu menu, Long userId) {
-        List<SysMenu> menuList = null;
-        // 绠$悊鍛樻樉绀烘墍鏈夎彍鍗曚俊鎭�
-        if (LoginHelper.isAdmin(userId)) {
-            menuList = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>()
-                .like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName())
-                .eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible())
-                .eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus())
-                .orderByAsc(SysMenu::getParentId)
-                .orderByAsc(SysMenu::getOrderNum));
-        } else {
-            QueryWrapper<SysMenu> wrapper = Wrappers.query();
-            wrapper.eq("sur.user_id", userId)
-                .like(StringUtils.isNotBlank(menu.getMenuName()), "m.menu_name", menu.getMenuName())
-                .eq(StringUtils.isNotBlank(menu.getVisible()), "m.visible", menu.getVisible())
-                .eq(StringUtils.isNotBlank(menu.getStatus()), "m.status", menu.getStatus())
-                .orderByAsc("m.parent_id")
-                .orderByAsc("m.order_num");
-            menuList = baseMapper.selectMenuListByUserId(wrapper);
-        }
-        return menuList;
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鏉冮檺鍒楄〃
-     */
-    @Override
-    public Set<String> selectMenuPermsByUserId(Long userId) {
-        List<String> perms = baseMapper.selectMenuPermsByUserId(userId);
-        Set<String> permsSet = new HashSet<>();
-        for (String perm : perms) {
-            if (StringUtils.isNotEmpty(perm)) {
-                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
-            }
-        }
-        return permsSet;
-    }
-
-    /**
-     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 鏉冮檺鍒楄〃
-     */
-    @Override
-    public Set<String> selectMenuPermsByRoleId(Long roleId) {
-        List<String> perms = baseMapper.selectMenuPermsByRoleId(roleId);
-        Set<String> permsSet = new HashSet<>();
-        for (String perm : perms) {
-            if (StringUtils.isNotEmpty(perm)) {
-                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
-            }
-        }
-        return permsSet;
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
-     *
-     * @param userId 鐢ㄦ埛鍚嶇О
-     * @return 鑿滃崟鍒楄〃
-     */
-    @Override
-    public List<SysMenu> selectMenuTreeByUserId(Long userId) {
-        List<SysMenu> menus = null;
-        if (LoginHelper.isAdmin(userId)) {
-            menus = baseMapper.selectMenuTreeAll();
-        } else {
-            menus = baseMapper.selectMenuTreeByUserId(userId);
-        }
-        return getChildPerms(menus, 0);
-    }
-
-    /**
-     * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 閫変腑鑿滃崟鍒楄〃
-     */
-    @Override
-    public List<Long> selectMenuListByRoleId(Long roleId) {
-        SysRole role = roleMapper.selectById(roleId);
-        return baseMapper.selectMenuListByRoleId(roleId, role.getMenuCheckStrictly());
-    }
-
-    /**
-     * 鏋勫缓鍓嶇璺敱鎵�闇�瑕佺殑鑿滃崟
-     *
-     * @param menus 鑿滃崟鍒楄〃
-     * @return 璺敱鍒楄〃
-     */
-    @Override
-    public List<RouterVo> buildMenus(List<SysMenu> menus) {
-        List<RouterVo> routers = new LinkedList<RouterVo>();
-        for (SysMenu menu : menus) {
-            RouterVo router = new RouterVo();
-            router.setHidden("1".equals(menu.getVisible()));
-            router.setName(getRouteName(menu));
-            router.setPath(getRouterPath(menu));
-            router.setComponent(getComponent(menu));
-            router.setQuery(menu.getQueryParam());
-            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
-            List<SysMenu> cMenus = menu.getChildren();
-            if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
-                router.setAlwaysShow(true);
-                router.setRedirect("noRedirect");
-                router.setChildren(buildMenus(cMenus));
-            } else if (isMenuFrame(menu)) {
-                router.setMeta(null);
-                List<RouterVo> childrenList = new ArrayList<RouterVo>();
-                RouterVo children = new RouterVo();
-                children.setPath(menu.getPath());
-                children.setComponent(menu.getComponent());
-                children.setName(StringUtils.capitalize(menu.getPath()));
-                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
-                children.setQuery(menu.getQueryParam());
-                childrenList.add(children);
-                router.setChildren(childrenList);
-            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
-                router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
-                router.setPath("/");
-                List<RouterVo> childrenList = new ArrayList<RouterVo>();
-                RouterVo children = new RouterVo();
-                String routerPath = innerLinkReplaceEach(menu.getPath());
-                children.setPath(routerPath);
-                children.setComponent(UserConstants.INNER_LINK);
-                children.setName(StringUtils.capitalize(routerPath));
-                children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
-                childrenList.add(children);
-                router.setChildren(childrenList);
-            }
-            routers.add(router);
-        }
-        return routers;
-    }
-
-    /**
-     * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
-     *
-     * @param menus 鑿滃崟鍒楄〃
-     * @return 涓嬫媺鏍戠粨鏋勫垪琛�
-     */
-    @Override
-    public List<Tree<Long>> buildMenuTreeSelect(List<SysMenu> menus) {
-        if (CollUtil.isEmpty(menus)) {
-            return CollUtil.newArrayList();
-        }
-        return TreeBuildUtils.build(menus, (menu, tree) ->
-            tree.setId(menu.getMenuId())
-                .setParentId(menu.getParentId())
-                .setName(menu.getMenuName())
-                .setWeight(menu.getOrderNum()));
-    }
-
-    /**
-     * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
-     *
-     * @param menuId 鑿滃崟ID
-     * @return 鑿滃崟淇℃伅
-     */
-    @Override
-    public SysMenu selectMenuById(Long menuId) {
-        return baseMapper.selectById(menuId);
-    }
-
-    /**
-     * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
-     *
-     * @param menuId 鑿滃崟ID
-     * @return 缁撴灉
-     */
-    @Override
-    public boolean hasChildByMenuId(Long menuId) {
-        return baseMapper.exists(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, menuId));
-    }
-
-    /**
-     * 鏌ヨ鑿滃崟浣跨敤鏁伴噺
-     *
-     * @param menuId 鑿滃崟ID
-     * @return 缁撴灉
-     */
-    @Override
-    public boolean checkMenuExistRole(Long menuId) {
-        return roleMenuMapper.exists(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getMenuId, menuId));
-    }
-
-    /**
-     * 鏂板淇濆瓨鑿滃崟淇℃伅
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int insertMenu(SysMenu menu) {
-        return baseMapper.insert(menu);
-    }
-
-    /**
-     * 淇敼淇濆瓨鑿滃崟淇℃伅
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updateMenu(SysMenu menu) {
-        return baseMapper.updateById(menu);
-    }
-
-    /**
-     * 鍒犻櫎鑿滃崟绠$悊淇℃伅
-     *
-     * @param menuId 鑿滃崟ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteMenuById(Long menuId) {
-        return baseMapper.deleteById(menuId);
-    }
-
-    /**
-     * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkMenuNameUnique(SysMenu menu) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysMenu>()
-            .eq(SysMenu::getMenuName, menu.getMenuName())
-            .eq(SysMenu::getParentId, menu.getParentId())
-            .ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鑾峰彇璺敱鍚嶇О
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 璺敱鍚嶇О
-     */
-    public String getRouteName(SysMenu menu) {
-        String routerName = StringUtils.capitalize(menu.getPath());
-        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
-        if (isMenuFrame(menu)) {
-            routerName = StringUtils.EMPTY;
-        }
-        return routerName;
-    }
-
-    /**
-     * 鑾峰彇璺敱鍦板潃
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 璺敱鍦板潃
-     */
-    public String getRouterPath(SysMenu menu) {
-        String routerPath = menu.getPath();
-        // 鍐呴摼鎵撳紑澶栫綉鏂瑰紡
-        if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
-            routerPath = innerLinkReplaceEach(routerPath);
-        }
-        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
-        if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
-            && UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
-            routerPath = "/" + menu.getPath();
-        }
-        // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓鸿彍鍗曪級
-        else if (isMenuFrame(menu)) {
-            routerPath = "/";
-        }
-        return routerPath;
-    }
-
-    /**
-     * 鑾峰彇缁勪欢淇℃伅
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁勪欢淇℃伅
-     */
-    public String getComponent(SysMenu menu) {
-        String component = UserConstants.LAYOUT;
-        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
-            component = menu.getComponent();
-        } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
-            component = UserConstants.INNER_LINK;
-        } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) {
-            component = UserConstants.PARENT_VIEW;
-        }
-        return component;
-    }
-
-    /**
-     * 鏄惁涓鸿彍鍗曞唴閮ㄨ烦杞�
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁撴灉
-     */
-    public boolean isMenuFrame(SysMenu menu) {
-        return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
-            && menu.getIsFrame().equals(UserConstants.NO_FRAME);
-    }
-
-    /**
-     * 鏄惁涓哄唴閾剧粍浠�
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁撴灉
-     */
-    public boolean isInnerLink(SysMenu menu) {
-        return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
-    }
-
-    /**
-     * 鏄惁涓簆arent_view缁勪欢
-     *
-     * @param menu 鑿滃崟淇℃伅
-     * @return 缁撴灉
-     */
-    public boolean isParentView(SysMenu menu) {
-        return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
-    }
-
-    /**
-     * 鏍规嵁鐖惰妭鐐圭殑ID鑾峰彇鎵�鏈夊瓙鑺傜偣
-     *
-     * @param list     鍒嗙被琛�
-     * @param parentId 浼犲叆鐨勭埗鑺傜偣ID
-     * @return String
-     */
-    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
-        List<SysMenu> returnList = new ArrayList<SysMenu>();
-        for (SysMenu t : list) {
-            // 涓�銆佹牴鎹紶鍏ョ殑鏌愪釜鐖惰妭鐐笽D,閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
-            if (t.getParentId() == parentId) {
-                recursionFn(list, t);
-                returnList.add(t);
-            }
-        }
-        return returnList;
-    }
-
-    /**
-     * 閫掑綊鍒楄〃
-     *
-     * @param list
-     * @param t
-     */
-    private void recursionFn(List<SysMenu> list, SysMenu t) {
-        // 寰楀埌瀛愯妭鐐瑰垪琛�
-        List<SysMenu> childList = getChildList(list, t);
-        t.setChildren(childList);
-        for (SysMenu tChild : childList) {
-            if (hasChild(list, tChild)) {
-                recursionFn(list, tChild);
-            }
-        }
-    }
-
-    /**
-     * 寰楀埌瀛愯妭鐐瑰垪琛�
-     */
-    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
-        return StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId()));
-    }
-
-    /**
-     * 鍒ゆ柇鏄惁鏈夊瓙鑺傜偣
-     */
-    private boolean hasChild(List<SysMenu> list, SysMenu t) {
-        return getChildList(list, t).size() > 0;
-    }
-
-    /**
-     * 鍐呴摼鍩熷悕鐗规畩瀛楃鏇挎崲
-     */
-    public String innerLinkReplaceEach(String path) {
-        return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, "."},
-            new String[]{"", "", "", "/"});
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
deleted file mode 100644
index 73a6736..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.domain.SysNotice;
-import com.ruoyi.system.mapper.SysNoticeMapper;
-import com.ruoyi.system.service.ISysNoticeService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 鍏憡 鏈嶅姟灞傚疄鐜�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysNoticeServiceImpl implements ISysNoticeService {
-
-    private final SysNoticeMapper baseMapper;
-
-    @Override
-    public TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice, PageQuery pageQuery) {
-        LambdaQueryWrapper<SysNotice> lqw = new LambdaQueryWrapper<SysNotice>()
-            .like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())
-            .eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())
-            .like(StringUtils.isNotBlank(notice.getCreateBy()), SysNotice::getCreateBy, notice.getCreateBy());
-        Page<SysNotice> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏌ヨ鍏憡淇℃伅
-     *
-     * @param noticeId 鍏憡ID
-     * @return 鍏憡淇℃伅
-     */
-    @Override
-    public SysNotice selectNoticeById(Long noticeId) {
-        return baseMapper.selectById(noticeId);
-    }
-
-    /**
-     * 鏌ヨ鍏憡鍒楄〃
-     *
-     * @param notice 鍏憡淇℃伅
-     * @return 鍏憡闆嗗悎
-     */
-    @Override
-    public List<SysNotice> selectNoticeList(SysNotice notice) {
-        return baseMapper.selectList(new LambdaQueryWrapper<SysNotice>()
-            .like(StringUtils.isNotBlank(notice.getNoticeTitle()), SysNotice::getNoticeTitle, notice.getNoticeTitle())
-            .eq(StringUtils.isNotBlank(notice.getNoticeType()), SysNotice::getNoticeType, notice.getNoticeType())
-            .like(StringUtils.isNotBlank(notice.getCreateBy()), SysNotice::getCreateBy, notice.getCreateBy()));
-    }
-
-    /**
-     * 鏂板鍏憡
-     *
-     * @param notice 鍏憡淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int insertNotice(SysNotice notice) {
-        return baseMapper.insert(notice);
-    }
-
-    /**
-     * 淇敼鍏憡
-     *
-     * @param notice 鍏憡淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updateNotice(SysNotice notice) {
-        return baseMapper.updateById(notice);
-    }
-
-    /**
-     * 鍒犻櫎鍏憡瀵硅薄
-     *
-     * @param noticeId 鍏憡ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteNoticeById(Long noticeId) {
-        return baseMapper.deleteById(noticeId);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鍏憡淇℃伅
-     *
-     * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteNoticeByIds(Long[] noticeIds) {
-        return baseMapper.deleteBatchIds(Arrays.asList(noticeIds));
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
deleted file mode 100644
index 28ac34c..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.util.ArrayUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.domain.event.OperLogEvent;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.ip.AddressUtils;
-import com.ruoyi.system.domain.SysOperLog;
-import com.ruoyi.system.mapper.SysOperLogMapper;
-import com.ruoyi.system.service.ISysOperLogService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.context.event.EventListener;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鎿嶄綔鏃ュ織 鏈嶅姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysOperLogServiceImpl implements ISysOperLogService {
-
-    private final SysOperLogMapper baseMapper;
-
-    /**
-     * 鎿嶄綔鏃ュ織璁板綍
-     *
-     * @param operLogEvent 鎿嶄綔鏃ュ織浜嬩欢
-     */
-    @Async
-    @EventListener
-    public void recordOper(OperLogEvent operLogEvent) {
-        SysOperLog operLog = BeanUtil.toBean(operLogEvent, SysOperLog.class);
-        // 杩滅▼鏌ヨ鎿嶄綔鍦扮偣
-        operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
-        insertOperlog(operLog);
-    }
-
-    @Override
-    public TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog, PageQuery pageQuery) {
-        Map<String, Object> params = operLog.getParams();
-        LambdaQueryWrapper<SysOperLog> lqw = new LambdaQueryWrapper<SysOperLog>()
-            .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
-            .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
-                SysOperLog::getBusinessType, operLog.getBusinessType())
-            .func(f -> {
-                if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
-                    f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
-                }
-            })
-            .eq(operLog.getStatus() != null,
-                SysOperLog::getStatus, operLog.getStatus())
-            .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"));
-        if (StringUtils.isBlank(pageQuery.getOrderByColumn())) {
-            pageQuery.setOrderByColumn("oper_id");
-            pageQuery.setIsAsc("desc");
-        }
-        Page<SysOperLog> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏂板鎿嶄綔鏃ュ織
-     *
-     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
-     */
-    @Override
-    public void insertOperlog(SysOperLog operLog) {
-        operLog.setOperTime(new Date());
-        baseMapper.insert(operLog);
-    }
-
-    /**
-     * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
-     *
-     * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
-     * @return 鎿嶄綔鏃ュ織闆嗗悎
-     */
-    @Override
-    public List<SysOperLog> selectOperLogList(SysOperLog operLog) {
-        Map<String, Object> params = operLog.getParams();
-        return baseMapper.selectList(new LambdaQueryWrapper<SysOperLog>()
-            .like(StringUtils.isNotBlank(operLog.getTitle()), SysOperLog::getTitle, operLog.getTitle())
-            .eq(operLog.getBusinessType() != null && operLog.getBusinessType() > 0,
-                SysOperLog::getBusinessType, operLog.getBusinessType())
-            .func(f -> {
-                if (ArrayUtil.isNotEmpty(operLog.getBusinessTypes())) {
-                    f.in(SysOperLog::getBusinessType, Arrays.asList(operLog.getBusinessTypes()));
-                }
-            })
-            .eq(operLog.getStatus() != null && operLog.getStatus() > 0,
-                SysOperLog::getStatus, operLog.getStatus())
-            .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime"))
-            .orderByDesc(SysOperLog::getOperId));
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
-     *
-     * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteOperLogByIds(Long[] operIds) {
-        return baseMapper.deleteBatchIds(Arrays.asList(operIds));
-    }
-
-    /**
-     * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
-     *
-     * @param operId 鎿嶄綔ID
-     * @return 鎿嶄綔鏃ュ織瀵硅薄
-     */
-    @Override
-    public SysOperLog selectOperLogById(Long operId) {
-        return baseMapper.selectById(operId);
-    }
-
-    /**
-     * 娓呯┖鎿嶄綔鏃ュ織
-     */
-    @Override
-    public void cleanOperLog() {
-        baseMapper.delete(new LambdaQueryWrapper<>());
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
deleted file mode 100644
index d626924..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.redis.CacheUtils;
-import com.ruoyi.common.utils.redis.RedisUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.oss.constant.OssConstant;
-import com.ruoyi.oss.factory.OssFactory;
-import com.ruoyi.system.domain.SysOssConfig;
-import com.ruoyi.system.domain.bo.SysOssConfigBo;
-import com.ruoyi.system.domain.vo.SysOssConfigVo;
-import com.ruoyi.system.mapper.SysOssConfigMapper;
-import com.ruoyi.system.service.ISysOssConfigService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 瀵硅薄瀛樺偍閰嶇疆Service涓氬姟灞傚鐞�
- *
- * @author Lion Li
- * @author 瀛よ垷鐑熼洦
- * @date 2021-08-13
- */
-@Slf4j
-@RequiredArgsConstructor
-@Service
-public class SysOssConfigServiceImpl implements ISysOssConfigService {
-
-    private final SysOssConfigMapper baseMapper;
-
-    /**
-     * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧弬鏁板埌缂撳瓨锛屽姞杞介厤缃被
-     */
-    @Override
-    public void init() {
-        List<SysOssConfig> list = baseMapper.selectList();
-        // 鍔犺浇OSS鍒濆鍖栭厤缃�
-        for (SysOssConfig config : list) {
-            String configKey = config.getConfigKey();
-            if ("0".equals(config.getStatus())) {
-                RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey);
-            }
-            SpringUtils.context().publishEvent(config);
-        }
-        // 鍒濆鍖朞SS宸ュ巶
-        OssFactory.init();
-    }
-
-    @Override
-    public SysOssConfigVo queryById(Long ossConfigId) {
-        return baseMapper.selectVoById(ossConfigId);
-    }
-
-    @Override
-    public TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<SysOssConfig> lqw = buildQueryWrapper(bo);
-        Page<SysOssConfigVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(result);
-    }
-
-
-    private LambdaQueryWrapper<SysOssConfig> buildQueryWrapper(SysOssConfigBo bo) {
-        LambdaQueryWrapper<SysOssConfig> lqw = Wrappers.lambdaQuery();
-        lqw.eq(StringUtils.isNotBlank(bo.getConfigKey()), SysOssConfig::getConfigKey, bo.getConfigKey());
-        lqw.like(StringUtils.isNotBlank(bo.getBucketName()), SysOssConfig::getBucketName, bo.getBucketName());
-        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SysOssConfig::getStatus, bo.getStatus());
-        return lqw;
-    }
-
-    @Override
-    public Boolean insertByBo(SysOssConfigBo bo) {
-        SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
-        validEntityBeforeSave(config);
-        boolean flag = baseMapper.insert(config) > 0;
-        if (flag) {
-            SpringUtils.context().publishEvent(config);
-        }
-        return flag;
-    }
-
-    @Override
-    public Boolean updateByBo(SysOssConfigBo bo) {
-        SysOssConfig config = BeanUtil.toBean(bo, SysOssConfig.class);
-        validEntityBeforeSave(config);
-        LambdaUpdateWrapper<SysOssConfig> luw = new LambdaUpdateWrapper<>();
-        luw.set(ObjectUtil.isNull(config.getPrefix()), SysOssConfig::getPrefix, "");
-        luw.set(ObjectUtil.isNull(config.getRegion()), SysOssConfig::getRegion, "");
-        luw.set(ObjectUtil.isNull(config.getExt1()), SysOssConfig::getExt1, "");
-        luw.set(ObjectUtil.isNull(config.getRemark()), SysOssConfig::getRemark, "");
-        luw.eq(SysOssConfig::getOssConfigId, config.getOssConfigId());
-        boolean flag = baseMapper.update(config, luw) > 0;
-        if (flag) {
-            SpringUtils.context().publishEvent(config);
-        }
-        return flag;
-    }
-
-    /**
-     * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
-     */
-    private void validEntityBeforeSave(SysOssConfig entity) {
-        if (StringUtils.isNotEmpty(entity.getConfigKey())
-            && UserConstants.NOT_UNIQUE.equals(checkConfigKeyUnique(entity))) {
-            throw new ServiceException("鎿嶄綔閰嶇疆'" + entity.getConfigKey() + "'澶辫触, 閰嶇疆key宸插瓨鍦�!");
-        }
-    }
-
-    @Override
-    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if (isValid) {
-            if (CollUtil.containsAny(ids, OssConstant.SYSTEM_DATA_IDS)) {
-                throw new ServiceException("绯荤粺鍐呯疆, 涓嶅彲鍒犻櫎!");
-            }
-        }
-        List<SysOssConfig> list = CollUtil.newArrayList();
-        for (Long configId : ids) {
-            SysOssConfig config = baseMapper.selectById(configId);
-            list.add(config);
-        }
-        boolean flag = baseMapper.deleteBatchIds(ids) > 0;
-        if (flag) {
-            list.forEach(sysOssConfig ->
-                CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey()));
-        }
-        return flag;
-    }
-
-    /**
-     * 鍒ゆ柇configKey鏄惁鍞竴
-     */
-    private String checkConfigKeyUnique(SysOssConfig sysOssConfig) {
-        long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId();
-        SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysOssConfig>()
-            .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey)
-            .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey()));
-        if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鍚敤绂佺敤鐘舵��
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int updateOssConfigStatus(SysOssConfigBo bo) {
-        SysOssConfig sysOssConfig = BeanUtil.toBean(bo, SysOssConfig.class);
-        int row = baseMapper.update(null, new LambdaUpdateWrapper<SysOssConfig>()
-            .set(SysOssConfig::getStatus, "1"));
-        row += baseMapper.updateById(sysOssConfig);
-        if (row > 0) {
-            RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, sysOssConfig.getConfigKey());
-        }
-        return row;
-    }
-
-    /**
-     * 鏇存柊閰嶇疆缂撳瓨
-     *
-     * @param config 閰嶇疆
-     */
-    @EventListener
-    public void updateConfigCache(SysOssConfig config) {
-        CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config));
-        RedisUtils.publish(OssConstant.DEFAULT_CONFIG_KEY, config.getConfigKey(), msg -> {
-            log.info("鍙戝竷鍒锋柊OSS閰嶇疆 => " + msg);
-        });
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
deleted file mode 100644
index 819cabb..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.CacheNames;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.BeanCopyUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.FileUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.oss.core.OssClient;
-import com.ruoyi.oss.entity.UploadResult;
-import com.ruoyi.oss.enumd.AccessPolicyType;
-import com.ruoyi.oss.factory.OssFactory;
-import com.ruoyi.system.domain.SysOss;
-import com.ruoyi.system.domain.bo.SysOssBo;
-import com.ruoyi.system.domain.vo.SysOssVo;
-import com.ruoyi.system.mapper.SysOssMapper;
-import com.ruoyi.system.service.ISysOssService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * 鏂囦欢涓婁紶 鏈嶅姟灞傚疄鐜�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysOssServiceImpl implements ISysOssService {
-
-    private final SysOssMapper baseMapper;
-
-    @Override
-    public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
-        Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        List<SysOssVo> filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList());
-        result.setRecords(filterResult);
-        return TableDataInfo.build(result);
-    }
-
-    @Override
-    public List<SysOssVo> listByIds(Collection<Long> ossIds) {
-        List<SysOssVo> list = new ArrayList<>();
-        for (Long id : ossIds) {
-            SysOssVo vo = SpringUtils.getAopProxy(this).getById(id);
-            if (ObjectUtil.isNotNull(vo)) {
-                list.add(this.matchingUrl(vo));
-            }
-        }
-        return list;
-    }
-
-    private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
-        Map<String, Object> params = bo.getParams();
-        LambdaQueryWrapper<SysOss> lqw = Wrappers.lambdaQuery();
-        lqw.like(StringUtils.isNotBlank(bo.getFileName()), SysOss::getFileName, bo.getFileName());
-        lqw.like(StringUtils.isNotBlank(bo.getOriginalName()), SysOss::getOriginalName, bo.getOriginalName());
-        lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), SysOss::getFileSuffix, bo.getFileSuffix());
-        lqw.eq(StringUtils.isNotBlank(bo.getUrl()), SysOss::getUrl, bo.getUrl());
-        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
-            SysOss::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
-        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), SysOss::getCreateBy, bo.getCreateBy());
-        lqw.eq(StringUtils.isNotBlank(bo.getService()), SysOss::getService, bo.getService());
-        return lqw;
-    }
-
-    @Cacheable(cacheNames = CacheNames.SYS_OSS, key = "#ossId")
-    @Override
-    public SysOssVo getById(Long ossId) {
-        return baseMapper.selectVoById(ossId);
-    }
-
-    @Override
-    public void download(Long ossId, HttpServletResponse response) throws IOException {
-        SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
-        if (ObjectUtil.isNull(sysOss)) {
-            throw new ServiceException("鏂囦欢鏁版嵁涓嶅瓨鍦�!");
-        }
-        FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
-        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
-        OssClient storage = OssFactory.instance();
-        try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) {
-            int available = inputStream.available();
-            IoUtil.copy(inputStream, response.getOutputStream(), available);
-            response.setContentLength(available);
-        } catch (Exception e) {
-            throw new ServiceException(e.getMessage());
-        }
-    }
-
-    @Override
-    public SysOssVo upload(MultipartFile file) {
-        String originalfileName = file.getOriginalFilename();
-        String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
-        OssClient storage = OssFactory.instance();
-        UploadResult uploadResult;
-        try {
-            uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
-        } catch (IOException e) {
-            throw new ServiceException(e.getMessage());
-        }
-        // 淇濆瓨鏂囦欢淇℃伅
-        SysOss oss = new SysOss();
-        oss.setUrl(uploadResult.getUrl());
-        oss.setFileSuffix(suffix);
-        oss.setFileName(uploadResult.getFilename());
-        oss.setOriginalName(originalfileName);
-        oss.setService(storage.getConfigKey());
-        baseMapper.insert(oss);
-        SysOssVo sysOssVo = new SysOssVo();
-        BeanCopyUtils.copy(oss, sysOssVo);
-        return this.matchingUrl(sysOssVo);
-    }
-
-    @Override
-    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if (isValid) {
-            // 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
-        }
-        List<SysOss> list = baseMapper.selectBatchIds(ids);
-        for (SysOss sysOss : list) {
-            OssClient storage = OssFactory.instance(sysOss.getService());
-            storage.delete(sysOss.getUrl());
-        }
-        return baseMapper.deleteBatchIds(ids) > 0;
-    }
-
-    /**
-     * 鍖归厤Url
-     *
-     * @param oss OSS瀵硅薄
-     * @return oss 鍖归厤Url鐨凮SS瀵硅薄
-     */
-    private SysOssVo matchingUrl(SysOssVo oss) {
-        OssClient storage = OssFactory.instance(oss.getService());
-        // 浠呬慨鏀规《绫诲瀷涓� private 鐨刄RL锛屼复鏃禪RL鏃堕暱涓�120s
-        if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
-            oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120));
-        }
-        return oss;
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
deleted file mode 100644
index 7e2a56c..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.domain.SysPost;
-import com.ruoyi.system.domain.SysUserPost;
-import com.ruoyi.system.mapper.SysPostMapper;
-import com.ruoyi.system.mapper.SysUserPostMapper;
-import com.ruoyi.system.service.ISysPostService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * 宀椾綅淇℃伅 鏈嶅姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysPostServiceImpl implements ISysPostService {
-
-    private final SysPostMapper baseMapper;
-    private final SysUserPostMapper userPostMapper;
-
-    @Override
-    public TableDataInfo<SysPost> selectPagePostList(SysPost post, PageQuery pageQuery) {
-        LambdaQueryWrapper<SysPost> lqw = new LambdaQueryWrapper<SysPost>()
-            .like(StringUtils.isNotBlank(post.getPostCode()), SysPost::getPostCode, post.getPostCode())
-            .eq(StringUtils.isNotBlank(post.getStatus()), SysPost::getStatus, post.getStatus())
-            .like(StringUtils.isNotBlank(post.getPostName()), SysPost::getPostName, post.getPostName());
-        Page<SysPost> page = baseMapper.selectPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏌ヨ宀椾綅淇℃伅闆嗗悎
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 宀椾綅淇℃伅闆嗗悎
-     */
-    @Override
-    public List<SysPost> selectPostList(SysPost post) {
-        return baseMapper.selectList(new LambdaQueryWrapper<SysPost>()
-            .like(StringUtils.isNotBlank(post.getPostCode()), SysPost::getPostCode, post.getPostCode())
-            .eq(StringUtils.isNotBlank(post.getStatus()), SysPost::getStatus, post.getStatus())
-            .like(StringUtils.isNotBlank(post.getPostName()), SysPost::getPostName, post.getPostName()));
-    }
-
-    /**
-     * 鏌ヨ鎵�鏈夊矖浣�
-     *
-     * @return 宀椾綅鍒楄〃
-     */
-    @Override
-    public List<SysPost> selectPostAll() {
-        return baseMapper.selectList();
-    }
-
-    /**
-     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
-     *
-     * @param postId 宀椾綅ID
-     * @return 瑙掕壊瀵硅薄淇℃伅
-     */
-    @Override
-    public SysPost selectPostById(Long postId) {
-        return baseMapper.selectById(postId);
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 閫変腑宀椾綅ID鍒楄〃
-     */
-    @Override
-    public List<Long> selectPostListByUserId(Long userId) {
-        return baseMapper.selectPostListByUserId(userId);
-    }
-
-    /**
-     * 鏍¢獙宀椾綅鍚嶇О鏄惁鍞竴
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkPostNameUnique(SysPost post) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>()
-            .eq(SysPost::getPostName, post.getPostName())
-            .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙宀椾綅缂栫爜鏄惁鍞竴
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkPostCodeUnique(SysPost post) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>()
-            .eq(SysPost::getPostCode, post.getPostCode())
-            .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
-     *
-     * @param postId 宀椾綅ID
-     * @return 缁撴灉
-     */
-    @Override
-    public long countUserPostById(Long postId) {
-        return userPostMapper.selectCount(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getPostId, postId));
-    }
-
-    /**
-     * 鍒犻櫎宀椾綅淇℃伅
-     *
-     * @param postId 宀椾綅ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deletePostById(Long postId) {
-        return baseMapper.deleteById(postId);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎宀椾綅淇℃伅
-     *
-     * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deletePostByIds(Long[] postIds) {
-        for (Long postId : postIds) {
-            SysPost post = selectPostById(postId);
-            if (countUserPostById(postId) > 0) {
-                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", post.getPostName()));
-            }
-        }
-        return baseMapper.deleteBatchIds(Arrays.asList(postIds));
-    }
-
-    /**
-     * 鏂板淇濆瓨宀椾綅淇℃伅
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int insertPost(SysPost post) {
-        return baseMapper.insert(post);
-    }
-
-    /**
-     * 淇敼淇濆瓨宀椾綅淇℃伅
-     *
-     * @param post 宀椾綅淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updatePost(SysPost post) {
-        return baseMapper.updateById(post);
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
deleted file mode 100644
index 0681a63..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
+++ /dev/null
@@ -1,412 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-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.toolkit.StringUtils;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.system.domain.SysRoleDept;
-import com.ruoyi.system.domain.SysRoleMenu;
-import com.ruoyi.system.domain.SysUserRole;
-import com.ruoyi.system.mapper.SysRoleDeptMapper;
-import com.ruoyi.system.mapper.SysRoleMapper;
-import com.ruoyi.system.mapper.SysRoleMenuMapper;
-import com.ruoyi.system.mapper.SysUserRoleMapper;
-import com.ruoyi.system.service.ISysRoleService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-
-/**
- * 瑙掕壊 涓氬姟灞傚鐞�
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@Service
-public class SysRoleServiceImpl implements ISysRoleService {
-
-    private final SysRoleMapper baseMapper;
-    private final SysRoleMenuMapper roleMenuMapper;
-    private final SysUserRoleMapper userRoleMapper;
-    private final SysRoleDeptMapper roleDeptMapper;
-
-    @Override
-    public TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery) {
-        Page<SysRole> page = baseMapper.selectPageRoleList(pageQuery.build(), this.buildQueryWrapper(role));
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
-     */
-    @Override
-    public List<SysRole> selectRoleList(SysRole role) {
-        return baseMapper.selectRoleList(this.buildQueryWrapper(role));
-    }
-
-    private Wrapper<SysRole> buildQueryWrapper(SysRole role) {
-        Map<String, Object> params = role.getParams();
-        QueryWrapper<SysRole> wrapper = Wrappers.query();
-        wrapper.eq("r.del_flag", UserConstants.ROLE_NORMAL)
-            .eq(ObjectUtil.isNotNull(role.getRoleId()), "r.role_id", role.getRoleId())
-            .like(StringUtils.isNotBlank(role.getRoleName()), "r.role_name", role.getRoleName())
-            .eq(StringUtils.isNotBlank(role.getStatus()), "r.status", role.getStatus())
-            .like(StringUtils.isNotBlank(role.getRoleKey()), "r.role_key", role.getRoleKey())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                "r.create_time", params.get("beginTime"), params.get("endTime"))
-            .orderByAsc("r.role_sort");
-        return wrapper;
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 瑙掕壊鍒楄〃
-     */
-    @Override
-    public List<SysRole> selectRolesByUserId(Long userId) {
-        List<SysRole> userRoles = baseMapper.selectRolePermissionByUserId(userId);
-        List<SysRole> roles = selectRoleAll();
-        for (SysRole role : roles) {
-            for (SysRole userRole : userRoles) {
-                if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) {
-                    role.setFlag(true);
-                    break;
-                }
-            }
-        }
-        return roles;
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鏉冮檺鍒楄〃
-     */
-    @Override
-    public Set<String> selectRolePermissionByUserId(Long userId) {
-        List<SysRole> perms = baseMapper.selectRolePermissionByUserId(userId);
-        Set<String> permsSet = new HashSet<>();
-        for (SysRole perm : perms) {
-            if (ObjectUtil.isNotNull(perm)) {
-                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
-            }
-        }
-        return permsSet;
-    }
-
-    /**
-     * 鏌ヨ鎵�鏈夎鑹�
-     *
-     * @return 瑙掕壊鍒楄〃
-     */
-    @Override
-    public List<SysRole> selectRoleAll() {
-        return this.selectRoleList(new SysRole());
-    }
-
-    /**
-     * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 閫変腑瑙掕壊ID鍒楄〃
-     */
-    @Override
-    public List<Long> selectRoleListByUserId(Long userId) {
-        return baseMapper.selectRoleListByUserId(userId);
-    }
-
-    /**
-     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 瑙掕壊瀵硅薄淇℃伅
-     */
-    @Override
-    public SysRole selectRoleById(Long roleId) {
-        return baseMapper.selectById(roleId);
-    }
-
-    /**
-     * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkRoleNameUnique(SysRole role) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>()
-            .eq(SysRole::getRoleName, role.getRoleName())
-            .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkRoleKeyUnique(SysRole role) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>()
-            .eq(SysRole::getRoleKey, role.getRoleKey())
-            .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
-     *
-     * @param role 瑙掕壊淇℃伅
-     */
-    @Override
-    public void checkRoleAllowed(SysRole role) {
-        if (ObjectUtil.isNotNull(role.getRoleId()) && role.isAdmin()) {
-            throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳瑙掕壊");
-        }
-    }
-
-    /**
-     * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
-     *
-     * @param roleId 瑙掕壊id
-     */
-    @Override
-    public void checkRoleDataScope(Long roleId) {
-        if (!LoginHelper.isAdmin()) {
-            SysRole role = new SysRole();
-            role.setRoleId(roleId);
-            List<SysRole> roles = this.selectRoleList(role);
-            if (CollUtil.isEmpty(roles)) {
-                throw new ServiceException("娌℃湁鏉冮檺璁块棶瑙掕壊鏁版嵁锛�");
-            }
-        }
-    }
-
-    /**
-     * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 缁撴灉
-     */
-    @Override
-    public long countUserRoleByRoleId(Long roleId) {
-        return userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
-    }
-
-    /**
-     * 鏂板淇濆瓨瑙掕壊淇℃伅
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int insertRole(SysRole role) {
-        // 鏂板瑙掕壊淇℃伅
-        baseMapper.insert(role);
-        return insertRoleMenu(role);
-    }
-
-    /**
-     * 淇敼淇濆瓨瑙掕壊淇℃伅
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int updateRole(SysRole role) {
-        // 淇敼瑙掕壊淇℃伅
-        baseMapper.updateById(role);
-        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
-        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, role.getRoleId()));
-        return insertRoleMenu(role);
-    }
-
-    /**
-     * 淇敼瑙掕壊鐘舵��
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updateRoleStatus(SysRole role) {
-        return baseMapper.updateById(role);
-    }
-
-    /**
-     * 淇敼鏁版嵁鏉冮檺淇℃伅
-     *
-     * @param role 瑙掕壊淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int authDataScope(SysRole role) {
-        // 淇敼瑙掕壊淇℃伅
-        baseMapper.updateById(role);
-        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
-        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().eq(SysRoleDept::getRoleId, role.getRoleId()));
-        // 鏂板瑙掕壊鍜岄儴闂ㄤ俊鎭紙鏁版嵁鏉冮檺锛�
-        return insertRoleDept(role);
-    }
-
-    /**
-     * 鏂板瑙掕壊鑿滃崟淇℃伅
-     *
-     * @param role 瑙掕壊瀵硅薄
-     */
-    public int insertRoleMenu(SysRole role) {
-        int rows = 1;
-        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
-        List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
-        for (Long menuId : role.getMenuIds()) {
-            SysRoleMenu rm = new SysRoleMenu();
-            rm.setRoleId(role.getRoleId());
-            rm.setMenuId(menuId);
-            list.add(rm);
-        }
-        if (list.size() > 0) {
-            rows = roleMenuMapper.insertBatch(list) ? list.size() : 0;
-        }
-        return rows;
-    }
-
-    /**
-     * 鏂板瑙掕壊閮ㄩ棬淇℃伅(鏁版嵁鏉冮檺)
-     *
-     * @param role 瑙掕壊瀵硅薄
-     */
-    public int insertRoleDept(SysRole role) {
-        int rows = 1;
-        // 鏂板瑙掕壊涓庨儴闂紙鏁版嵁鏉冮檺锛夌鐞�
-        List<SysRoleDept> list = new ArrayList<SysRoleDept>();
-        for (Long deptId : role.getDeptIds()) {
-            SysRoleDept rd = new SysRoleDept();
-            rd.setRoleId(role.getRoleId());
-            rd.setDeptId(deptId);
-            list.add(rd);
-        }
-        if (list.size() > 0) {
-            rows = roleDeptMapper.insertBatch(list) ? list.size() : 0;
-        }
-        return rows;
-    }
-
-    /**
-     * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
-     *
-     * @param roleId 瑙掕壊ID
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int deleteRoleById(Long roleId) {
-        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
-        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
-        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
-        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().eq(SysRoleDept::getRoleId, roleId));
-        return baseMapper.deleteById(roleId);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
-     *
-     * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int deleteRoleByIds(Long[] roleIds) {
-        for (Long roleId : roleIds) {
-            checkRoleAllowed(new SysRole(roleId));
-            checkRoleDataScope(roleId);
-            SysRole role = selectRoleById(roleId);
-            if (countUserRoleByRoleId(roleId) > 0) {
-                throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", role.getRoleName()));
-            }
-        }
-        List<Long> ids = Arrays.asList(roleIds);
-        // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
-        roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, ids));
-        // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
-        roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().in(SysRoleDept::getRoleId, ids));
-        return baseMapper.deleteBatchIds(ids);
-    }
-
-    /**
-     * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
-     *
-     * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteAuthUser(SysUserRole userRole) {
-        return userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
-            .eq(SysUserRole::getRoleId, userRole.getRoleId())
-            .eq(SysUserRole::getUserId, userRole.getUserId()));
-    }
-
-    /**
-     * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
-     *
-     * @param roleId  瑙掕壊ID
-     * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int deleteAuthUsers(Long roleId, Long[] userIds) {
-        return userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
-            .eq(SysUserRole::getRoleId, roleId)
-            .in(SysUserRole::getUserId, Arrays.asList(userIds)));
-    }
-
-    /**
-     * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
-     *
-     * @param roleId  瑙掕壊ID
-     * @param userIds 闇�瑕佹巿鏉冪殑鐢ㄦ埛鏁版嵁ID
-     * @return 缁撴灉
-     */
-    @Override
-    public int insertAuthUsers(Long roleId, Long[] userIds) {
-        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
-        int rows = 1;
-        List<SysUserRole> list = new ArrayList<SysUserRole>();
-        for (Long userId : userIds) {
-            SysUserRole ur = new SysUserRole();
-            ur.setUserId(userId);
-            ur.setRoleId(roleId);
-            list.add(ur);
-        }
-        if (list.size() > 0) {
-            rows = userRoleMapper.insertBatch(list) ? list.size() : 0;
-        }
-        return rows;
-    }
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java
deleted file mode 100644
index fe142ca..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSensitiveServiceImpl.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import com.ruoyi.common.core.service.SensitiveService;
-import com.ruoyi.common.helper.LoginHelper;
-import org.springframework.stereotype.Service;
-
-/**
- * 鑴辨晱鏈嶅姟
- * 榛樿绠$悊鍛樹笉杩囨护
- * 闇�鑷鏍规嵁涓氬姟閲嶅啓瀹炵幇
- *
- * @author Lion Li
- * @version 3.6.0
- */
-@Service
-public class SysSensitiveServiceImpl implements SensitiveService {
-
-    /**
-     * 鏄惁鑴辨晱
-     */
-    @Override
-    public boolean isSensitive() {
-        return !LoginHelper.isAdmin();
-    }
-
-}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
deleted file mode 100644
index 19430ba..0000000
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ /dev/null
@@ -1,488 +0,0 @@
-package com.ruoyi.system.service.impl;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-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.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.PageQuery;
-import com.ruoyi.system.domain.SysDept;
-import com.ruoyi.system.domain.SysRole;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.helper.DataBaseHelper;
-import com.ruoyi.common.helper.LoginHelper;
-import com.ruoyi.common.utils.StreamUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.domain.SysPost;
-import com.ruoyi.system.domain.SysUserPost;
-import com.ruoyi.system.domain.SysUserRole;
-import com.ruoyi.system.mapper.*;
-import com.ruoyi.system.service.ISysUserService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 鐢ㄦ埛 涓氬姟灞傚鐞�
- *
- * @author Lion Li
- */
-@Slf4j
-@RequiredArgsConstructor
-@Service
-public class SysUserServiceImpl implements ISysUserService {
-
-    private final SysUserMapper baseMapper;
-    private final SysDeptMapper deptMapper;
-    private final SysRoleMapper roleMapper;
-    private final SysPostMapper postMapper;
-    private final SysUserRoleMapper userRoleMapper;
-    private final SysUserPostMapper userPostMapper;
-
-    @Override
-    public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) {
-        Page<SysUser> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user));
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    @Override
-    public List<SysUser> selectUserList(SysUser user) {
-        return baseMapper.selectUserList(this.buildQueryWrapper(user));
-    }
-
-    private Wrapper<SysUser> buildQueryWrapper(SysUser user) {
-        Map<String, Object> params = user.getParams();
-        QueryWrapper<SysUser> wrapper = Wrappers.query();
-        wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
-            .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId())
-            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
-            .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
-            .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber())
-            .between(params.get("beginTime") != null && params.get("endTime") != null,
-                "u.create_time", params.get("beginTime"), params.get("endTime"))
-            .and(ObjectUtil.isNotNull(user.getDeptId()), w -> {
-                List<SysDept> deptList = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
-                    .select(SysDept::getDeptId)
-                    .apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors")));
-                List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
-                ids.add(user.getDeptId());
-                w.in("u.dept_id", ids);
-            });
-        return wrapper;
-    }
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    @Override
-    public TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery) {
-        QueryWrapper<SysUser> wrapper = Wrappers.query();
-        wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
-            .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId())
-            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
-            .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
-            .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
-        Page<SysUser> page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
-     */
-    @Override
-    public TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery) {
-        List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId());
-        QueryWrapper<SysUser> wrapper = Wrappers.query();
-        wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
-            .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id"))
-            .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds)
-            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
-            .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
-        Page<SysUser> page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper);
-        return TableDataInfo.build(page);
-    }
-
-    /**
-     * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    @Override
-    public SysUser selectUserByUserName(String userName) {
-        return baseMapper.selectUserByUserName(userName);
-    }
-
-    /**
-     * 閫氳繃鎵嬫満鍙锋煡璇㈢敤鎴�
-     *
-     * @param phonenumber 鎵嬫満鍙�
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    @Override
-    public SysUser selectUserByPhonenumber(String phonenumber) {
-        return baseMapper.selectUserByPhonenumber(phonenumber);
-    }
-
-    /**
-     * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 鐢ㄦ埛瀵硅薄淇℃伅
-     */
-    @Override
-    public SysUser selectUserById(Long userId) {
-        return baseMapper.selectUserById(userId);
-    }
-
-    /**
-     * 鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 缁撴灉
-     */
-    @Override
-    public String selectUserRoleGroup(String userName) {
-        List<SysRole> list = roleMapper.selectRolesByUserName(userName);
-        if (CollUtil.isEmpty(list)) {
-            return StringUtils.EMPTY;
-        }
-        return StreamUtils.join(list, SysRole::getRoleName);
-    }
-
-    /**
-     * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @return 缁撴灉
-     */
-    @Override
-    public String selectUserPostGroup(String userName) {
-        List<SysPost> list = postMapper.selectPostsByUserName(userName);
-        if (CollUtil.isEmpty(list)) {
-            return StringUtils.EMPTY;
-        }
-        return StreamUtils.join(list, SysPost::getPostName);
-    }
-
-    /**
-     * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public String checkUserNameUnique(SysUser user) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
-            .eq(SysUser::getUserName, user.getUserName())
-            .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return
-     */
-    @Override
-    public String checkPhoneUnique(SysUser user) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
-            .eq(SysUser::getPhonenumber, user.getPhonenumber())
-            .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙email鏄惁鍞竴
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return
-     */
-    @Override
-    public String checkEmailUnique(SysUser user) {
-        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
-            .eq(SysUser::getEmail, user.getEmail())
-            .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId()));
-        if (exist) {
-            return UserConstants.NOT_UNIQUE;
-        }
-        return UserConstants.UNIQUE;
-    }
-
-    /**
-     * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     */
-    @Override
-    public void checkUserAllowed(SysUser user) {
-        if (ObjectUtil.isNotNull(user.getUserId()) && user.isAdmin()) {
-            throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳鐢ㄦ埛");
-        }
-    }
-
-    /**
-     * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
-     *
-     * @param userId 鐢ㄦ埛id
-     */
-    @Override
-    public void checkUserDataScope(Long userId) {
-        if (!LoginHelper.isAdmin()) {
-            SysUser user = new SysUser();
-            user.setUserId(userId);
-            List<SysUser> users = this.selectUserList(user);
-            if (CollUtil.isEmpty(users)) {
-                throw new ServiceException("娌℃湁鏉冮檺璁块棶鐢ㄦ埛鏁版嵁锛�");
-            }
-        }
-    }
-
-    /**
-     * 鏂板淇濆瓨鐢ㄦ埛淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int insertUser(SysUser user) {
-        // 鏂板鐢ㄦ埛淇℃伅
-        int rows = baseMapper.insert(user);
-        // 鏂板鐢ㄦ埛宀椾綅鍏宠仈
-        insertUserPost(user);
-        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
-        insertUserRole(user);
-        return rows;
-    }
-
-    /**
-     * 娉ㄥ唽鐢ㄦ埛淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public boolean registerUser(SysUser user) {
-        user.setCreateBy(user.getUserName());
-        user.setUpdateBy(user.getUserName());
-        return baseMapper.insert(user) > 0;
-    }
-
-    /**
-     * 淇敼淇濆瓨鐢ㄦ埛淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int updateUser(SysUser user) {
-        Long userId = user.getUserId();
-        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
-        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
-        // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
-        insertUserRole(user);
-        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶅叧鑱�
-        userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));
-        // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
-        insertUserPost(user);
-        return baseMapper.updateById(user);
-    }
-
-    /**
-     * 鐢ㄦ埛鎺堟潈瑙掕壊
-     *
-     * @param userId  鐢ㄦ埛ID
-     * @param roleIds 瑙掕壊缁�
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void insertUserAuth(Long userId, Long[] roleIds) {
-        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
-            .eq(SysUserRole::getUserId, userId));
-        insertUserRole(userId, roleIds);
-    }
-
-    /**
-     * 淇敼鐢ㄦ埛鐘舵��
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updateUserStatus(SysUser user) {
-        return baseMapper.updateById(user);
-    }
-
-    /**
-     * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int updateUserProfile(SysUser user) {
-        return baseMapper.updateById(user);
-    }
-
-    /**
-     * 淇敼鐢ㄦ埛澶村儚
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @param avatar   澶村儚鍦板潃
-     * @return 缁撴灉
-     */
-    @Override
-    public boolean updateUserAvatar(String userName, String avatar) {
-        return baseMapper.update(null,
-            new LambdaUpdateWrapper<SysUser>()
-                .set(SysUser::getAvatar, avatar)
-                .eq(SysUser::getUserName, userName)) > 0;
-    }
-
-    /**
-     * 閲嶇疆鐢ㄦ埛瀵嗙爜
-     *
-     * @param user 鐢ㄦ埛淇℃伅
-     * @return 缁撴灉
-     */
-    @Override
-    public int resetPwd(SysUser user) {
-        return baseMapper.updateById(user);
-    }
-
-    /**
-     * 閲嶇疆鐢ㄦ埛瀵嗙爜
-     *
-     * @param userName 鐢ㄦ埛鍚�
-     * @param password 瀵嗙爜
-     * @return 缁撴灉
-     */
-    @Override
-    public int resetUserPwd(String userName, String password) {
-        return baseMapper.update(null,
-            new LambdaUpdateWrapper<SysUser>()
-                .set(SysUser::getPassword, password)
-                .eq(SysUser::getUserName, userName));
-    }
-
-    /**
-     * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
-     *
-     * @param user 鐢ㄦ埛瀵硅薄
-     */
-    public void insertUserRole(SysUser user) {
-        this.insertUserRole(user.getUserId(), user.getRoleIds());
-    }
-
-    /**
-     * 鏂板鐢ㄦ埛宀椾綅淇℃伅
-     *
-     * @param user 鐢ㄦ埛瀵硅薄
-     */
-    public void insertUserPost(SysUser user) {
-        Long[] posts = user.getPostIds();
-        if (ArrayUtil.isNotEmpty(posts)) {
-            // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
-            List<SysUserPost> list = new ArrayList<>(posts.length);
-            for (Long postId : posts) {
-                SysUserPost up = new SysUserPost();
-                up.setUserId(user.getUserId());
-                up.setPostId(postId);
-                list.add(up);
-            }
-            userPostMapper.insertBatch(list);
-        }
-    }
-
-    /**
-     * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
-     *
-     * @param userId  鐢ㄦ埛ID
-     * @param roleIds 瑙掕壊缁�
-     */
-    public void insertUserRole(Long userId, Long[] roleIds) {
-        if (ArrayUtil.isNotEmpty(roleIds)) {
-            // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
-            List<SysUserRole> list = new ArrayList<>(roleIds.length);
-            for (Long roleId : roleIds) {
-                SysUserRole ur = new SysUserRole();
-                ur.setUserId(userId);
-                ur.setRoleId(roleId);
-                list.add(ur);
-            }
-            userRoleMapper.insertBatch(list);
-        }
-    }
-
-    /**
-     * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
-     *
-     * @param userId 鐢ㄦ埛ID
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int deleteUserById(Long userId) {
-        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
-        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
-        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶈〃
-        userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().eq(SysUserPost::getUserId, userId));
-        return baseMapper.deleteById(userId);
-    }
-
-    /**
-     * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
-     *
-     * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
-     * @return 缁撴灉
-     */
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public int deleteUserByIds(Long[] userIds) {
-        for (Long userId : userIds) {
-            checkUserAllowed(new SysUser(userId));
-            checkUserDataScope(userId);
-        }
-        List<Long> ids = Arrays.asList(userIds);
-        // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
-        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));
-        // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶈〃
-        userPostMapper.delete(new LambdaQueryWrapper<SysUserPost>().in(SysUserPost::getUserId, ids));
-        return baseMapper.deleteBatchIds(ids);
-    }
-
-}

--
Gitblit v1.9.3