From dd37247e65374dd4ef7e8e8b9212d8f29023e301 Mon Sep 17 00:00:00 2001
From: 疯狂的狮子li <15040126243@163.com>
Date: 星期一, 27 十二月 2021 09:50:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into satoken

---
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java                                   |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java                                              |    7 
 ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestTreeServiceImpl.java                                      |   12 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java                                             |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java                                             |   26 
 ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm                                                     |   14 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java                                               |   72 
 ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java                                    |    9 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java                      |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java                                                |    3 
 ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java                                                     |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java                                                  |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java                              |   77 
 ruoyi-ui/package.json                                                                                              |    4 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java                                              |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java                               |    8 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java                            |    3 
 ruoyi-generator/src/main/resources/vm/java/controller.java.vm                                                      |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java                                              |   18 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java                               |   10 
 ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml                                                    |   16 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java                                              |    8 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java                                                   |   18 
 ruoyi-generator/src/main/resources/vm/java/bo.java.vm                                                              |   24 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/ValidatorUtils.java                                              |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java                                    |   11 
 ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm                                                          |  577 +++++++
 ruoyi-admin/src/main/resources/application.yml                                                                     |    8 
 ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java                                                  |   32 
 ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java                           |  192 ++
 ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java                                        |    4 
 ruoyi-ui/src/plugins/modal.js                                                                                      |    8 
 ruoyi-admin/src/main/resources/application-prod.yml                                                                |    4 
 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusDataPermissionInterceptor.java                   |  108 +
 ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java                                                           |   26 
 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java                                    |    5 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java                                        |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java                                         |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java                                            |    3 
 ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java                  |    6 
 ruoyi-admin/src/main/resources/application-dev.yml                                                                 |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java                                 |    8 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java                                                  |  129 +
 ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java |   12 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java                                        |    2 
 ruoyi-extend/ruoyi-xxl-job-admin/pom.xml                                                                           |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java                                   |   13 
 ruoyi-ui/src/views/tool/gen/index.vue                                                                              |    7 
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                                                    |   16 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java                                              |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java                             |   11 
 ruoyi-ui/src/views/system/menu/index.vue                                                                           |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java                              |   11 
 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java                             |    2 
 pom.xml                                                                                                            |   69 
 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java                                           |   27 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java                                           |    5 
 ruoyi-ui/src/components/Crontab/hour.vue                                                                           |   40 
 ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java                                                 |   39 
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataPermission.java                                         |   18 
 ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java                                 |   20 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java                                         |    3 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java                               |    5 
 ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java                                         |    7 
 ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java                             |   65 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java                                               |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java                                               |   98 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java                                                |   54 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java                                          |   25 
 ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java                                        |   10 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java                                                |   22 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java                                                   |   41 
 ruoyi-ui/src/views/tool/gen/basicInfoForm.vue                                                                      |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java                                                   |    3 
 ruoyi-framework/pom.xml                                                                                            |   20 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java                                           |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java                                              |    2 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java                                           |   33 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java                              |   50 
 ruoyi-ui/src/components/Crontab/day.vue                                                                            |   66 
 ruoyi-ui/src/utils/request.js                                                                                      |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java                                           |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java                                   |  111 -
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java                                             |    2 
 ruoyi-ui/src/components/Crontab/index.vue                                                                          |    9 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java                                   |    5 
 ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml                                             |   24 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java                                    |    5 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java                                             |   93 +
 ruoyi-ui/src/views/tool/gen/genInfoForm.vue                                                                        |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java                                |   60 
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java                                   |    2 
 ruoyi-ui/src/views/system/user/index.vue                                                                           |    4 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java                                                 |   26 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java                                    |   38 
 ruoyi-admin/src/main/resources/i18n/messages_en_US.properties                                                      |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java                                           |   41 
 ruoyi-ui/src/views/system/user/authRole.vue                                                                        |    2 
 ruoyi-ui/src/views/tool/gen/editTable.vue                                                                          |    1 
 ruoyi-ui/src/main.js                                                                                               |    3 
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java                                    |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java                                        |   11 
 ruoyi-ui/src/components/Crontab/result.vue                                                                         |   21 
 ruoyi-ui/src/router/index.js                                                                                       |   39 
 ruoyi-ui/src/components/Crontab/month.vue                                                                          |   46 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java                                 |   13 
 ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm                                                     |  476 +++++
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java                                     |    3 
 ruoyi-generator/src/main/resources/vm/java/service.java.vm                                                         |    3 
 ruoyi-ui/vue.config.js                                                                                             |   20 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java                                      |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeBuildUtils.java                                              |   12 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java                                 |    5 
 README.md                                                                                                          |    8 
 ruoyi-ui/src/directive/module/clipboard.js                                                                         |   54 
 script/docker/nginx/nginx.conf                                                                                     |   16 
 ruoyi-ui/src/directive/index.js                                                                                    |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java                                       |   45 
 ruoyi-ui/src/components/Crontab/min.vue                                                                            |   30 
 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java                    |   92 +
 ruoyi-admin/src/main/resources/i18n/messages.properties                                                            |    8 
 ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt                                                            |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java                                              |    2 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java                                |    5 
 ruoyi-ui/src/components/Crontab/year.vue                                                                           |   43 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java                                            |   48 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java                                       |    3 
 ruoyi-ui/src/plugins/download.js                                                                                   |   20 
 ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml                                                    |   26 
 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java                                               |    2 
 ruoyi-ui/src/views/monitor/online/index.vue                                                                        |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java                                             |   82 
 ruoyi-common/src/main/java/com/ruoyi/common/core/page/PagePlus.java                                                |    2 
 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java                                     |    7 
 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java                                       |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java                                        |    3 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java                                               |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/service/SysDataScopeService.java                                       |   24 
 ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties                                                      |    8 
 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml                                                    |   12 
 ruoyi-ui/src/components/Crontab/week.vue                                                                           |  107 
 ruoyi-ui/src/components/ImagePreview/index.vue                                                                     |   67 
 ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java                                                  |   25 
 ruoyi-demo/src/main/java/com/ruoyi/demo/service/impl/TestDemoServiceImpl.java                                      |   26 
 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java                                          |    7 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java                                       |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java                                           |   16 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java                                   |   10 
 script/docker/redis/redis.conf                                                                                     |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java                                |   11 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java                                   |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java                                   |   22 
 ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java                                              |    5 
 ruoyi-ui/src/store/modules/permission.js                                                                           |   22 
 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java                                 |    2 
 ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java                                                  |   21 
 ruoyi-ui/src/components/Crontab/second.vue                                                                         |   42 
 ruoyi-common/pom.xml                                                                                               |   64 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java                              |    5 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java                                                 |    3 
 ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java     |   10 
 /dev/null                                                                                                          |   85 -
 ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java                                                |   11 
 ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml                                                    |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java                                   |   13 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java                               |    5 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java                                          |  301 +-
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java                                      |    2 
 ruoyi-job/pom.xml                                                                                                  |    2 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java                               |    5 
 ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java                                                 |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java                                   |   21 
 ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java                                    |    9 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java                            |    5 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java                                 |    5 
 ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java                                                     |   12 
 176 files changed, 3,571 insertions(+), 1,347 deletions(-)

diff --git a/README.md b/README.md
index 7004f0e..33801da 100644
--- a/README.md
+++ b/README.md
@@ -8,21 +8,21 @@
 [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.5-blue.svg)]()
 [![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]()
 [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]()
-[![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]()
 
-> RuoYi-Vue-Plus 鏄熀浜� RuoYi-Vue 閽堝 `鍒嗗竷寮忛泦缇 鍦烘櫙鍗囩骇(涓嶅吋瀹瑰師妗嗘灦)
+> RuoYi-Vue-Plus 鏄噸鍐� RuoYi-Vue 閽堝 `鍒嗗竷寮忛泦缇 鍦烘櫙鍏ㄦ柟浣嶅崌绾�(涓嶅吋瀹瑰師妗嗘灦)
 
 > 绯荤粺婕旂ず: [浼犻�侀棬](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/绯荤粺婕旂ず?sort_id=4836388)
 
 | 鍔熻兘浠嬬粛 | 浣跨敤鎶�鏈� | 鏂囨。鍦板潃 | 鐗规�ф敞鎰忎簨椤� |
 |---|---|---|---|
 | 褰撳墠妗嗘灦 | RuoYi-Vue-Plus | [RuoYi-Vue-Plus鏂囨。](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) | 閲嶅啓RuoYi-Vue鍏ㄦ柟浣嶅崌绾�(涓嶅吋瀹瑰師妗嗘灦) |
-| satoken鍒嗘敮 | RuoYi-Vue-Plus-satoken | [satoken鍒嗘敮鍦板潃](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/) | 浣跨敤satoken閲嶆瀯鏉冮檺閴存潈(鍏祴 鍙皾璇曚笂鐢熶骇) |
+| satoken鍒嗘敮 | RuoYi-Vue-Plus-satoken | [satoken鍒嗘敮鍦板潃](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/satoken/) | 楂樺彲璇绘�� 鎵╁睍鎬�(鎺ㄨ崘浣跨敤) |
 | 鍗曚綋鍒嗘敮 | RuoYi-Vue-Plus-fast | [fast鍒嗘敮鍦板潃](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/tree/fast/) | 鍗曚綋搴旂敤缁撴瀯 |
+| Vue3鍒嗘敮 | RuoYi-Vue-Plus-UI | [UI鍦板潃](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus-UI) | 鐢变簬缁勪欢杩樻湭瀹屽杽 浠呬緵瀛︿範 |
 | 鍘熸鏋� | RuoYi-Vue | [RuoYi-Vue瀹樼綉](http://ruoyi.vip/) | 瀹氭湡鍚屾闇�瑕佺殑鍔熻兘 |
 | 鍓嶇寮�鍙戞鏋� | Vue銆丒lement UI | [Element UI瀹樼綉](https://element.eleme.cn/#/zh-CN) | |
 | 鍚庣寮�鍙戞鏋� | SpringBoot | [SpringBoot瀹樼綉](https://spring.io/projects/spring-boot/#learn) | |
-| 瀹瑰櫒妗嗘灦 | Undertow | [Undertow瀹樼綉](https://undertow.io/) | 鍩轰簬 Netty 鐨勯珮鎬ц兘瀹瑰櫒 |
+| 瀹瑰櫒妗嗘灦 | Undertow | [Undertow瀹樼綉](https://undertow.io/) | 鍩轰簬 XNIO 鐨勯珮鎬ц兘瀹瑰櫒 |
 | 鏉冮檺璁よ瘉妗嗘灦 | Spring Security銆丣wt | [SpringSecurity瀹樼綉](https://spring.io/projects/spring-security#learn) | 鏀寔澶氱粓绔璇佺郴缁� |
 | 鍏崇郴鏁版嵁搴� | MySQL | [MySQL瀹樼綉](https://dev.mysql.com/) | 閫傞厤 8.X 鏈�浣� 5.7 |
 | 缂撳瓨鏁版嵁搴� | Redis | [Redis瀹樼綉](https://redis.io/) | 閫傞厤 6.X 鏈�浣� 4.X |
diff --git a/pom.xml b/pom.xml
index db8b6b9..286d8fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
 
     <properties>
         <ruoyi-vue-plus.version>3.4.0</ruoyi-vue-plus.version>
-        <spring-boot.version>2.5.7</spring-boot.version>
+        <spring-boot.version>2.5.8</spring-boot.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>
@@ -24,27 +24,28 @@
         <swagger-annotations.version>1.5.22</swagger-annotations.version>
         <poi.version>4.1.2</poi.version>
         <easyexcel.version>2.2.11</easyexcel.version>
+        <cglib.version>3.3.0</cglib.version>
         <velocity.version>2.3</velocity.version>
         <satoken.version>1.28.0</satoken.version>
         <mybatis-plus.version>3.4.3.4</mybatis-plus.version>
         <p6spy.version>3.9.1</p6spy.version>
-        <hutool.version>5.7.16</hutool.version>
+        <hutool.version>5.7.17</hutool.version>
         <okhttp.version>4.9.2</okhttp.version>
-        <spring-boot-admin.version>2.5.4</spring-boot-admin.version>
-        <redisson.version>3.16.4</redisson.version>
+        <spring-boot-admin.version>2.5.5</spring-boot-admin.version>
+        <redisson.version>3.16.6</redisson.version>
         <lock4j.version>2.2.1</lock4j.version>
-        <dynamic-ds.version>3.4.1</dynamic-ds.version>
-        <tlog.version>1.3.4</tlog.version>
+        <dynamic-ds.version>3.5.0</dynamic-ds.version>
+        <tlog.version>1.3.6</tlog.version>
         <xxl-job.version>2.3.0</xxl-job.version>
 
         <!-- jdk11 缂哄け渚濊禆 jaxb-->
         <jaxb.version>3.0.1</jaxb.version>
 
         <!-- OSS 閰嶇疆 -->
-        <qiniu.version>7.8.0</qiniu.version>
+        <qiniu.version>7.9.0</qiniu.version>
         <aliyun.oss.version>3.13.1</aliyun.oss.version>
         <qcloud.cos.version>5.6.58</qcloud.cos.version>
-        <minio.version>8.3.3</minio.version>
+        <minio.version>8.3.4</minio.version>
 
         <!-- docker 閰嶇疆 -->
         <docker.registry.url>localhost</docker.registry.url>
@@ -115,6 +116,12 @@
                 </exclusions>
             </dependency>
 
+            <dependency>
+                <groupId>cglib</groupId>
+                <artifactId>cglib</artifactId>
+                <version>${cglib.version}</version>
+            </dependency>
+
             <!-- velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
             <dependency>
                 <groupId>org.apache.velocity</groupId>
@@ -168,7 +175,31 @@
 
             <dependency>
                 <groupId>cn.hutool</groupId>
-                <artifactId>hutool-all</artifactId>
+                <artifactId>hutool-core</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-http</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-captcha</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-extra</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-jwt</artifactId>
                 <version>${hutool.version}</version>
             </dependency>
 
@@ -210,29 +241,13 @@
 
             <dependency>
                 <groupId>com.yomahub</groupId>
-                <artifactId>tlog-spring-boot-configuration</artifactId>
+                <artifactId>tlog-web-spring-boot-starter</artifactId>
                 <version>${tlog.version}</version>
             </dependency>
 
             <dependency>
                 <groupId>com.yomahub</groupId>
-                <artifactId>tlog-webroot</artifactId>
-                <version>${tlog.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <artifactId>javassist</artifactId>
-                        <groupId>org.javassist</groupId>
-                    </exclusion>
-                    <exclusion>
-                        <artifactId>guava</artifactId>
-                        <groupId>com.google.guava</groupId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-
-            <dependency>
-                <groupId>com.yomahub</groupId>
-                <artifactId>tlog-xxl-job</artifactId>
+                <artifactId>tlog-xxljob-spring-boot-starter</artifactId>
                 <version>${tlog.version}</version>
             </dependency>
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
index cd02bba..22acf31 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -36,8 +37,8 @@
     @ApiOperation("鏌ヨ绯荤粺璁块棶璁板綍鍒楄〃")
     @SaCheckPermission("monitor:logininfor:list")
     @GetMapping("/list")
-    public TableDataInfo<SysLogininfor> list(SysLogininfor logininfor) {
-        return logininforService.selectPageLogininforList(logininfor);
+    public TableDataInfo<SysLogininfor> list(SysLogininfor logininfor, PageQuery pageQuery) {
+        return logininforService.selectPageLogininforList(logininfor, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭绯荤粺璁块棶璁板綍鍒楄〃")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
index 6978101..e510429 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -36,8 +37,8 @@
     @ApiOperation("鏌ヨ鎿嶄綔鏃ュ織璁板綍鍒楄〃")
     @SaCheckPermission("monitor:operlog:list")
     @GetMapping("/list")
-    public TableDataInfo<SysOperLog> list(SysOperLog operLog) {
-        return operLogService.selectPageOperLogList(operLog);
+    public TableDataInfo<SysOperLog> list(SysOperLog operLog, PageQuery pageQuery) {
+        return operLogService.selectPageOperLogList(operLog, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭鎿嶄綔鏃ュ織璁板綍鍒楄〃")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
index 2faf331..0f71c07 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
@@ -12,7 +12,6 @@
 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.PageUtils;
 import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysUserOnline;
@@ -70,7 +69,7 @@
         Collections.reverse(userOnlineDTOList);
         userOnlineDTOList.removeAll(Collections.singleton(null));
         List<SysUserOnline> userOnlineList = BeanUtil.copyToList(userOnlineDTOList, SysUserOnline.class);
-        return PageUtils.buildDataInfo(userOnlineList);
+        return TableDataInfo.build(userOnlineList);
     }
 
     /**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
index f5dac6f..0b8a928 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
@@ -5,6 +5,7 @@
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -41,8 +42,8 @@
     @ApiOperation("鑾峰彇鍙傛暟閰嶇疆鍒楄〃")
     @SaCheckPermission("system:config:list")
     @GetMapping("/list")
-    public TableDataInfo<SysConfig> list(SysConfig config) {
-        return configService.selectPageConfigList(config);
+    public TableDataInfo<SysConfig> list(SysConfig config, PageQuery pageQuery) {
+        return configService.selectPageConfigList(config, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭鍙傛暟閰嶇疆鍒楄〃")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
index 6d472d7..851cf4e 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
@@ -41,8 +42,8 @@
     @ApiOperation("鏌ヨ瀛楀吀鏁版嵁鍒楄〃")
     @SaCheckPermission("system:dict:list")
     @GetMapping("/list")
-    public TableDataInfo<SysDictData> list(SysDictData dictData) {
-        return dictDataService.selectPageDictDataList(dictData);
+    public TableDataInfo<SysDictData> list(SysDictData dictData, PageQuery pageQuery) {
+        return dictDataService.selectPageDictDataList(dictData, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭瀛楀吀鏁版嵁鍒楄〃")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
index 1e54404..9d98f9b 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
@@ -5,6 +5,7 @@
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDictType;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
@@ -38,8 +39,8 @@
     @ApiOperation("鏌ヨ瀛楀吀绫诲瀷鍒楄〃")
     @SaCheckPermission("system:dict:list")
     @GetMapping("/list")
-    public TableDataInfo<SysDictType> list(SysDictType dictType) {
-        return dictTypeService.selectPageDictTypeList(dictType);
+    public TableDataInfo<SysDictType> list(SysDictType dictType, PageQuery pageQuery) {
+        return dictTypeService.selectPageDictTypeList(dictType, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭瀛楀吀绫诲瀷鍒楄〃")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
index 31ed439..23e8593 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.system.domain.SysNotice;
@@ -36,8 +37,8 @@
     @ApiOperation("鑾峰彇閫氱煡鍏憡鍒楄〃")
     @SaCheckPermission("system:notice:list")
     @GetMapping("/list")
-    public TableDataInfo<SysNotice> list(SysNotice notice) {
-        return noticeService.selectPageNoticeList(notice);
+    public TableDataInfo<SysNotice> list(SysNotice notice, PageQuery pageQuery) {
+        return noticeService.selectPageNoticeList(notice, pageQuery);
     }
 
     /**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
index 18dfd51..0562cdf 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
@@ -5,6 +5,7 @@
 import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
@@ -47,8 +48,8 @@
     @ApiOperation("鏌ヨ瀵硅薄瀛樺偍閰嶇疆鍒楄〃")
     @SaCheckPermission("system:oss:list")
     @GetMapping("/list")
-    public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo) {
-        return iSysOssConfigService.queryPageList(bo);
+    public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) {
+        return iSysOssConfigService.queryPageList(bo, pageQuery);
     }
 
     /**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
index 5d229c8..41b8eab 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
@@ -11,6 +11,7 @@
 import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
@@ -61,8 +62,8 @@
     @ApiOperation("鏌ヨOSS瀵硅薄瀛樺偍鍒楄〃")
     @SaCheckPermission("system:oss:list")
     @GetMapping("/list")
-    public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo) {
-        return iSysOssService.queryPageList(bo);
+    public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) {
+        return iSysOssService.queryPageList(bo, pageQuery);
     }
 
     /**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
index b41d75b..6b383a4 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
@@ -5,6 +5,7 @@
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -41,8 +42,8 @@
     @ApiOperation("鑾峰彇宀椾綅鍒楄〃")
     @SaCheckPermission("system:post:list")
     @GetMapping("/list")
-    public TableDataInfo<SysPost> list(SysPost post) {
-        return postService.selectPagePostList(post);
+    public TableDataInfo<SysPost> list(SysPost post, PageQuery pageQuery) {
+        return postService.selectPagePostList(post, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭宀椾綅鍒楄〃")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
index ee97048..d0f80c7 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
@@ -11,7 +11,10 @@
 import com.ruoyi.system.domain.SysOss;
 import com.ruoyi.system.service.ISysOssService;
 import com.ruoyi.system.service.ISysUserService;
-import io.swagger.annotations.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
index 1e82188..ee0a4d4 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -5,6 +5,7 @@
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
@@ -45,8 +46,8 @@
     @ApiOperation("鏌ヨ瑙掕壊淇℃伅鍒楄〃")
     @SaCheckPermission("system:role:list")
     @GetMapping("/list")
-    public TableDataInfo<SysRole> list(SysRole role) {
-        return roleService.selectPageRoleList(role);
+    public TableDataInfo<SysRole> list(SysRole role, PageQuery pageQuery) {
+        return roleService.selectPageRoleList(role, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭瑙掕壊淇℃伅鍒楄〃")
@@ -165,8 +166,8 @@
     @ApiOperation("鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�")
     @SaCheckPermission("system:role:list")
     @GetMapping("/authUser/allocatedList")
-    public TableDataInfo<SysUser> allocatedList(SysUser user) {
-        return userService.selectAllocatedList(user);
+    public TableDataInfo<SysUser> allocatedList(SysUser user, PageQuery pageQuery) {
+        return userService.selectAllocatedList(user, pageQuery);
     }
 
     /**
@@ -175,8 +176,8 @@
     @ApiOperation("鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�")
     @SaCheckPermission("system:role:list")
     @GetMapping("/authUser/unallocatedList")
-    public TableDataInfo<SysUser> unallocatedList(SysUser user) {
-        return userService.selectUnallocatedList(user);
+    public TableDataInfo<SysUser> unallocatedList(SysUser user, PageQuery pageQuery) {
+        return userService.selectUnallocatedList(user, pageQuery);
     }
 
     /**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index bd77f61..b6a22b5 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -8,6 +8,7 @@
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
@@ -59,8 +60,8 @@
     @ApiOperation("鑾峰彇鐢ㄦ埛鍒楄〃")
     @SaCheckPermission("system:user:list")
     @GetMapping("/list")
-    public TableDataInfo<SysUser> list(SysUser user) {
-        return userService.selectPageUserList(user);
+    public TableDataInfo<SysUser> list(SysUser user, PageQuery pageQuery) {
+        return userService.selectPageUserList(user, pageQuery);
     }
 
     @ApiOperation("瀵煎嚭鐢ㄦ埛鍒楄〃")
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 015b302..c9b246b 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -51,7 +51,9 @@
         # 涓诲簱鏁版嵁婧�
         master:
           driverClassName: com.mysql.cj.jdbc.Driver
-          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
+          # jdbc 鎵�鏈夊弬鏁伴厤缃弬鑰� https://lionli.blog.csdn.net/article/details/122018562
+          # rewriteBatchedStatements=true 鎵瑰鐞嗕紭鍖� 澶у箙鎻愬崌鎵归噺鎻掑叆鏇存柊鍒犻櫎鎬ц兘(瀵规暟鎹簱鏈夋�ц兘鎹熻�� 浣跨敤鎵归噺鎿嶄綔搴旇�冭檻鎬ц兘闂)
+          url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
           username: root
           password: root
         # 浠庡簱鏁版嵁婧�
diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml
index 1d680d7..cfa8c7c 100644
--- a/ruoyi-admin/src/main/resources/application-prod.yml
+++ b/ruoyi-admin/src/main/resources/application-prod.yml
@@ -58,7 +58,9 @@
         # 涓诲簱鏁版嵁婧�
         master:
           driverClassName: com.mysql.cj.jdbc.Driver
-          url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
+          # jdbc 鎵�鏈夊弬鏁伴厤缃弬鑰� https://lionli.blog.csdn.net/article/details/122018562
+          # rewriteBatchedStatements=true 鎵瑰鐞嗕紭鍖� 澶у箙鎻愬崌鎵归噺鎻掑叆鏇存柊鍒犻櫎鎬ц兘(瀵规暟鎹簱鏈夋�ц兘鎹熻�� 浣跨敤鎵归噺鎿嶄綔搴旇�冭檻鎬ц兘闂)
+          url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
           username: root
           password: root
         # 浠庡簱鏁版嵁婧�
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index dbd182f..a232f86 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -11,7 +11,7 @@
   # 鑾峰彇ip鍦板潃寮�鍏�
   addressEnabled: true
   # 缂撳瓨鎳掑姞杞�
-  cacheLazy: true
+  cacheLazy: false
 
 captcha:
   # 椤甸潰 <鍙傛暟璁剧疆> 鍙紑鍚叧闂� 楠岃瘉鐮佹牎楠�
@@ -52,10 +52,6 @@
     com.ruoyi: @logging.level@
     org.springframework: warn
   config: classpath:logback.xml
-
-# tlog 鍏ㄥ眬璁块棶鎬ц兘鎷︽埅
-tlog:
-  enable-invoke-time-print: true
 
 # Spring閰嶇疆
 spring:
@@ -142,6 +138,8 @@
     - /*/api-docs
     # druid 鐩戞帶閰嶇疆
     - /druid/**
+  # 鐢ㄦ埛鏀捐
+  permit-all:
     # actuator 鐩戞帶閰嶇疆
     - /actuator
     - /actuator/**
diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties
index ede2df8..6db4b42 100644
--- a/ruoyi-admin/src/main/resources/i18n/messages.properties
+++ b/ruoyi-admin/src/main/resources/i18n/messages.properties
@@ -2,12 +2,12 @@
 not.null=* 蹇呴』濉啓
 user.jcaptcha.error=楠岃瘉鐮侀敊璇�
 user.jcaptcha.expire=楠岃瘉鐮佸凡澶辨晥
-user.not.exists=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
+user.not.exists=瀵逛笉璧�, 鎮ㄧ殑璐﹀彿锛歿0} 涓嶅瓨鍦�.
 user.password.not.match=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
 user.password.retry.limit.count=瀵嗙爜杈撳叆閿欒{0}娆�
-user.password.retry.limit.exceed=瀵嗙爜杈撳叆閿欒{0}娆★紝甯愭埛閿佸畾10鍒嗛挓
-user.password.delete=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿宸茶鍒犻櫎
-user.blocked=鐢ㄦ埛宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
+user.password.retry.limit.exceed=瀵嗙爜閿欒娆℃暟杩囧锛屽笎鎴烽攣瀹歿0}鍒嗛挓
+user.password.delete=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛歿0} 宸茶鍒犻櫎
+user.blocked=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛歿0} 宸茬鐢紝璇疯仈绯荤鐞嗗憳
 role.blocked=瑙掕壊宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
 user.logout.success=閫�鍑烘垚鍔�
 length.not.valid=闀垮害蹇呴』鍦▄min}鍒皗max}涓瓧绗︿箣闂�
diff --git a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
index af57cf4..c67beab 100644
--- a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
+++ b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
@@ -2,12 +2,12 @@
 not.null=* Required fill in
 user.jcaptcha.error=Captcha error
 user.jcaptcha.expire=Captcha invalid
-user.not.exists=User does not exist/Password error
+user.not.exists=Sorry, your account: {0} does not exist
 user.password.not.match=User does not exist/Password error
 user.password.retry.limit.count=Password input error {0} times
-user.password.retry.limit.exceed=Password input error {0} times, account locked for 10 minutes
-user.password.delete=Sorry, your account has been deleted
-user.blocked=User disabled锛宲lease contact administrators
+user.password.retry.limit.exceed=Too many password errors, account locked for {0} minutes
+user.password.delete=Sorry, your account锛歿0} has been deleted
+user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
 role.blocked=Role disabled锛宲lease contact administrators
 user.logout.success=Exit successful
 length.not.valid=The length must be between {min} and {max} characters
diff --git a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
index ede2df8..6db4b42 100644
--- a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
+++ b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
@@ -2,12 +2,12 @@
 not.null=* 蹇呴』濉啓
 user.jcaptcha.error=楠岃瘉鐮侀敊璇�
 user.jcaptcha.expire=楠岃瘉鐮佸凡澶辨晥
-user.not.exists=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
+user.not.exists=瀵逛笉璧�, 鎮ㄧ殑璐﹀彿锛歿0} 涓嶅瓨鍦�.
 user.password.not.match=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
 user.password.retry.limit.count=瀵嗙爜杈撳叆閿欒{0}娆�
-user.password.retry.limit.exceed=瀵嗙爜杈撳叆閿欒{0}娆★紝甯愭埛閿佸畾10鍒嗛挓
-user.password.delete=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿宸茶鍒犻櫎
-user.blocked=鐢ㄦ埛宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
+user.password.retry.limit.exceed=瀵嗙爜閿欒娆℃暟杩囧锛屽笎鎴烽攣瀹歿0}鍒嗛挓
+user.password.delete=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛歿0} 宸茶鍒犻櫎
+user.blocked=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛歿0} 宸茬鐢紝璇疯仈绯荤鐞嗗憳
 role.blocked=瑙掕壊宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
 user.logout.success=閫�鍑烘垚鍔�
 length.not.valid=闀垮害蹇呴』鍦▄min}鍒皗max}涓瓧绗︿箣闂�
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 37282f4..9788097 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -74,17 +74,16 @@
             <artifactId>easyexcel</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+        </dependency>
+
         <!-- yml瑙f瀽鍣� -->
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
         </dependency>
-
-<!--        &lt;!&ndash;Token鐢熸垚涓庤В鏋�&ndash;&gt;-->
-<!--        <dependency>-->
-<!--            <groupId>io.jsonwebtoken</groupId>-->
-<!--            <artifactId>jjwt</artifactId>-->
-<!--        </dependency>-->
 
         <!-- jdk11 缂哄け渚濊禆 jaxb-->
         <dependency>
@@ -106,18 +105,41 @@
             <groupId>com.baomidou</groupId>
             <artifactId>mybatis-plus-extension</artifactId>
         </dependency>
+
+        <!-- dynamic-datasource 澶氭暟鎹簮-->
         <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-all</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
+            <groupId>com.baomidou</groupId>
+            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
         </dependency>
 
         <dependency>
-            <groupId>de.codecentric</groupId>
-            <artifactId>spring-boot-admin-starter-client</artifactId>
+            <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>
 
         <dependency>
@@ -130,10 +152,6 @@
             <artifactId>swagger-annotations</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-actuator</artifactId>
-        </dependency>
         <!--  鑷姩鐢熸垚YML閰嶇疆鍏宠仈JSON鏂囦欢  -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -149,16 +167,6 @@
         <dependency>
             <groupId>com.baomidou</groupId>
             <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.yomahub</groupId>
-            <artifactId>tlog-spring-boot-configuration</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.yomahub</groupId>
-            <artifactId>tlog-webroot</artifactId>
         </dependency>
 
     </dependencies>
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
new file mode 100644
index 0000000..bd2ddec
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 鏁版嵁鏉冮檺
+ *
+ * @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
new file mode 100644
index 0000000..73d9c03
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataPermission.java
@@ -0,0 +1,18 @@
+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/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
index feaa3f4..f1a4f9f 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
@@ -6,11 +6,14 @@
  * 鏁版嵁鏉冮檺杩囨护娉ㄨВ
  *
  * @author ruoyi
+ * @deprecated 3.6.0 绉婚櫎 {@link com.ruoyi.common.annotation.DataPermission}
  */
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
+@Deprecated
 public @interface DataScope {
+
     /**
      * 閮ㄩ棬琛ㄧ殑鍒悕
      */
@@ -25,4 +28,5 @@
      * 鏄惁杩囨护鐢ㄦ埛鏉冮檺
      */
     boolean isUser() default false;
+
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
index e7d2250..9bbc812 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
@@ -10,11 +10,13 @@
  * 浼樺厛绾э細鍏堟柟娉曪紝鍚庣被锛屽鏋滄柟娉曡鐩栦簡绫讳笂鐨勬暟鎹簮绫诲瀷锛屼互鏂规硶鐨勪负鍑嗭紝鍚﹀垯浠ョ被涓婄殑涓哄噯
  *
  * @author ruoyi
+ * @deprecated 3.6.0 绉婚櫎 浣跨敤鍘熺敓娉ㄨВ澶勭悊 鏂规硶鏇村叏 {@link com.baomidou.dynamic.datasource.annotation.DS}
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Inherited
+@Deprecated
 public @interface DataSource {
     /**
      * 鍒囨崲鏁版嵁婧愬悕绉�
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
index fc1137b..1ffcbfb 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -5,61 +5,62 @@
  *
  * @author ruoyi
  */
-public class Constants {
+public interface Constants {
+
     /**
      * UTF-8 瀛楃闆�
      */
-    public static final String UTF8 = "UTF-8";
+    String UTF8 = "UTF-8";
 
     /**
      * GBK 瀛楃闆�
      */
-    public static final String GBK = "GBK";
+    String GBK = "GBK";
 
     /**
      * http璇锋眰
      */
-    public static final String HTTP = "http://";
+    String HTTP = "http://";
 
     /**
      * https璇锋眰
      */
-    public static final String HTTPS = "https://";
+    String HTTPS = "https://";
 
     /**
      * 閫氱敤鎴愬姛鏍囪瘑
      */
-    public static final String SUCCESS = "0";
+    String SUCCESS = "0";
 
     /**
      * 閫氱敤澶辫触鏍囪瘑
      */
-    public static final String FAIL = "1";
+    String FAIL = "1";
 
     /**
      * 鐧诲綍鎴愬姛
      */
-    public static final String LOGIN_SUCCESS = "Success";
+    String LOGIN_SUCCESS = "Success";
 
     /**
      * 娉ㄩ攢
      */
-    public static final String LOGOUT = "Logout";
+    String LOGOUT = "Logout";
 
     /**
      * 娉ㄥ唽
      */
-    public static final String REGISTER = "Register";
+    String REGISTER = "Register";
 
     /**
      * 鐧诲綍澶辫触
      */
-    public static final String LOGIN_FAIL = "Error";
+    String LOGIN_FAIL = "Error";
 
     /**
      * 楠岃瘉鐮� redis key
      */
-    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+    String CAPTCHA_CODE_KEY = "captcha_codes:";
 
     /**
      * 鐧诲綍鐢ㄦ埛 redis key
@@ -74,36 +75,51 @@
     /**
      * 闃查噸鎻愪氦 redis key
      */
-    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+    String REPEAT_SUBMIT_KEY = "repeat_submit:";
 
     /**
      * 闄愭祦 redis key
      */
-    public static final String RATE_LIMIT_KEY = "rate_limit:";
+    String RATE_LIMIT_KEY = "rate_limit:";
 
     /**
      * 楠岃瘉鐮佹湁鏁堟湡锛堝垎閽燂級
      */
-    public static final Integer CAPTCHA_EXPIRATION = 2;
+    Integer CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 鐧婚檰閿欒 redis key
+     */
+    String LOGIN_ERROR = "login_error:";
+
+    /**
+     * 鐧诲綍閿欒娆℃暟
+     */
+    Integer LOGIN_ERROR_NUMBER = 5;
+
+    /**
+     * 鐧诲綍閿欒闄愬埗鏃堕棿(鍒嗛挓)
+     */
+    Integer LOGIN_ERROR_LIMIT_TIME = 10;
 
     /**
      * 浠ょ墝
      */
-    public static final String TOKEN = "token";
+    String TOKEN = "token";
 
     /**
      * 浠ょ墝鍓嶇紑
      */
-    public static final String LOGIN_USER_KEY = "login_user_key";
+    String LOGIN_USER_KEY = "login_user_key";
 
     /**
      * 鍙傛暟绠$悊 cache key
      */
-    public static final String SYS_CONFIG_KEY = "sys_config:";
+    String SYS_CONFIG_KEY = "sys_config:";
 
     /**
      * 瀛楀吀绠$悊 cache key
      */
-    public static final String SYS_DICT_KEY = "sys_dict:";
+    String SYS_DICT_KEY = "sys_dict:";
 
 }
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
index 4d0a4e8..60bf881 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
@@ -5,184 +5,184 @@
  *
  * @author ruoyi
  */
-public class GenConstants {
+public interface GenConstants {
     /**
      * 鍗曡〃锛堝鍒犳敼鏌ワ級
      */
-    public static final String TPL_CRUD = "crud";
+    String TPL_CRUD = "crud";
 
     /**
      * 鏍戣〃锛堝鍒犳敼鏌ワ級
      */
-    public static final String TPL_TREE = "tree";
+    String TPL_TREE = "tree";
 
     /**
      * 涓诲瓙琛紙澧炲垹鏀规煡锛�
      */
-    public static final String TPL_SUB = "sub";
+    String TPL_SUB = "sub";
 
     /**
      * 鏍戠紪鐮佸瓧娈�
      */
-    public static final String TREE_CODE = "treeCode";
+    String TREE_CODE = "treeCode";
 
     /**
      * 鏍戠埗缂栫爜瀛楁
      */
-    public static final String TREE_PARENT_CODE = "treeParentCode";
+    String TREE_PARENT_CODE = "treeParentCode";
 
     /**
      * 鏍戝悕绉板瓧娈�
      */
-    public static final String TREE_NAME = "treeName";
+    String TREE_NAME = "treeName";
 
     /**
      * 涓婄骇鑿滃崟ID瀛楁
      */
-    public static final String PARENT_MENU_ID = "parentMenuId";
+    String PARENT_MENU_ID = "parentMenuId";
 
     /**
      * 涓婄骇鑿滃崟鍚嶇О瀛楁
      */
-    public static final String PARENT_MENU_NAME = "parentMenuName";
+    String PARENT_MENU_NAME = "parentMenuName";
 
     /**
      * 鏁版嵁搴撳瓧绗︿覆绫诲瀷
      */
-    public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
+    String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
 
     /**
      * 鏁版嵁搴撴枃鏈被鍨�
      */
-    public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
+    String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
 
     /**
      * 鏁版嵁搴撴椂闂寸被鍨�
      */
-    public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
+    String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
 
     /**
      * 鏁版嵁搴撴暟瀛楃被鍨�
      */
-    public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
-            "bit", "bigint", "float", "double", "decimal"};
+    String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
+        "bit", "bigint", "float", "double", "decimal"};
 
     /**
      * BO瀵硅薄 涓嶉渶瑕佹坊鍔犲瓧娈�
      */
-    public static final String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time", "del_flag", "update_by",
-            "update_time", "version"};
+    String[] COLUMNNAME_NOT_ADD = {"create_by", "create_time", "del_flag", "update_by",
+        "update_time", "version"};
 
     /**
      * BO瀵硅薄 涓嶉渶瑕佺紪杈戝瓧娈�
      */
-    public static final String[] COLUMNNAME_NOT_EDIT = {"create_by", "create_time", "del_flag", "update_by",
-            "update_time", "version"};
+    String[] COLUMNNAME_NOT_EDIT = {"create_by", "create_time", "del_flag", "update_by",
+        "update_time", "version"};
 
     /**
      * VO瀵硅薄 涓嶉渶瑕佽繑鍥炲瓧娈�
      */
-    public static final String[] COLUMNNAME_NOT_LIST = {"create_by", "create_time", "del_flag", "update_by",
-            "update_time", "version"};
+    String[] COLUMNNAME_NOT_LIST = {"create_by", "create_time", "del_flag", "update_by",
+        "update_time", "version"};
 
     /**
      * BO瀵硅薄 涓嶉渶瑕佹煡璇㈠瓧娈�
      */
-    public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
-            "update_time", "remark", "version"};
+    String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
+        "update_time", "remark", "version"};
 
     /**
      * Entity鍩虹被瀛楁
      */
-    public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime"};
+    String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime"};
 
     /**
      * Tree鍩虹被瀛楁
      */
-    public static final String[] TREE_ENTITY = {"parentName", "parentId", "children"};
+    String[] TREE_ENTITY = {"parentName", "parentId", "children"};
 
     /**
      * 鏂囨湰妗�
      */
-    public static final String HTML_INPUT = "input";
+    String HTML_INPUT = "input";
 
     /**
      * 鏂囨湰鍩�
      */
-    public static final String HTML_TEXTAREA = "textarea";
+    String HTML_TEXTAREA = "textarea";
 
     /**
      * 涓嬫媺妗�
      */
-    public static final String HTML_SELECT = "select";
+    String HTML_SELECT = "select";
 
     /**
      * 鍗曢�夋
      */
-    public static final String HTML_RADIO = "radio";
+    String HTML_RADIO = "radio";
 
     /**
      * 澶嶉�夋
      */
-    public static final String HTML_CHECKBOX = "checkbox";
+    String HTML_CHECKBOX = "checkbox";
 
     /**
      * 鏃ユ湡鎺т欢
      */
-    public static final String HTML_DATETIME = "datetime";
+    String HTML_DATETIME = "datetime";
 
     /**
      * 鍥剧墖涓婁紶鎺т欢
      */
-    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+    String HTML_IMAGE_UPLOAD = "imageUpload";
 
     /**
      * 鏂囦欢涓婁紶鎺т欢
      */
-    public static final String HTML_FILE_UPLOAD = "fileUpload";
+    String HTML_FILE_UPLOAD = "fileUpload";
 
     /**
      * 瀵屾枃鏈帶浠�
      */
-    public static final String HTML_EDITOR = "editor";
+    String HTML_EDITOR = "editor";
 
     /**
      * 瀛楃涓茬被鍨�
      */
-    public static final String TYPE_STRING = "String";
+    String TYPE_STRING = "String";
 
     /**
      * 鏁村瀷
      */
-    public static final String TYPE_INTEGER = "Integer";
+    String TYPE_INTEGER = "Integer";
 
     /**
      * 闀挎暣鍨�
      */
-    public static final String TYPE_LONG = "Long";
+    String TYPE_LONG = "Long";
 
     /**
      * 娴偣鍨�
      */
-    public static final String TYPE_DOUBLE = "Double";
+    String TYPE_DOUBLE = "Double";
 
     /**
      * 楂樼簿搴﹁绠楃被鍨�
      */
-    public static final String TYPE_BIGDECIMAL = "BigDecimal";
+    String TYPE_BIGDECIMAL = "BigDecimal";
 
     /**
      * 鏃堕棿绫诲瀷
      */
-    public static final String TYPE_DATE = "Date";
+    String TYPE_DATE = "Date";
 
     /**
      * 妯$硦鏌ヨ
      */
-    public static final String QUERY_LIKE = "LIKE";
+    String QUERY_LIKE = "LIKE";
 
     /**
      * 闇�瑕�
      */
-    public static final String REQUIRE = "1";
+    String REQUIRE = "1";
 }
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
index fa88e7c..eebbb4b 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -5,108 +5,108 @@
  *
  * @author ruoyi
  */
-public class UserConstants {
+public interface UserConstants {
 
     /**
      * 骞冲彴鍐呯郴缁熺敤鎴风殑鍞竴鏍囧織
      */
-    public static final String SYS_USER = "SYS_USER";
+    String SYS_USER = "SYS_USER";
 
     /**
      * 姝e父鐘舵��
      */
-    public static final String NORMAL = "0";
+    String NORMAL = "0";
 
     /**
      * 寮傚父鐘舵��
      */
-    public static final String EXCEPTION = "1";
+    String EXCEPTION = "1";
 
     /**
      * 鐢ㄦ埛灏佺鐘舵��
      */
-    public static final String USER_DISABLE = "1";
+    String USER_DISABLE = "1";
 
     /**
      * 瑙掕壊灏佺鐘舵��
      */
-    public static final String ROLE_DISABLE = "1";
+    String ROLE_DISABLE = "1";
 
     /**
      * 閮ㄩ棬姝e父鐘舵��
      */
-    public static final String DEPT_NORMAL = "0";
+    String DEPT_NORMAL = "0";
 
     /**
      * 閮ㄩ棬鍋滅敤鐘舵��
      */
-    public static final String DEPT_DISABLE = "1";
+    String DEPT_DISABLE = "1";
 
     /**
      * 瀛楀吀姝e父鐘舵��
      */
-    public static final String DICT_NORMAL = "0";
+    String DICT_NORMAL = "0";
 
     /**
      * 鏄惁涓虹郴缁熼粯璁わ紙鏄級
      */
-    public static final String YES = "Y";
+    String YES = "Y";
 
     /**
      * 鏄惁鑿滃崟澶栭摼锛堟槸锛�
      */
-    public static final String YES_FRAME = "0";
+    String YES_FRAME = "0";
 
     /**
      * 鏄惁鑿滃崟澶栭摼锛堝惁锛�
      */
-    public static final String NO_FRAME = "1";
+    String NO_FRAME = "1";
 
     /**
      * 鑿滃崟绫诲瀷锛堢洰褰曪級
      */
-    public static final String TYPE_DIR = "M";
+    String TYPE_DIR = "M";
 
     /**
      * 鑿滃崟绫诲瀷锛堣彍鍗曪級
      */
-    public static final String TYPE_MENU = "C";
+    String TYPE_MENU = "C";
 
     /**
      * 鑿滃崟绫诲瀷锛堟寜閽級
      */
-    public static final String TYPE_BUTTON = "F";
+    String TYPE_BUTTON = "F";
 
     /**
      * Layout缁勪欢鏍囪瘑
      */
-    public final static String LAYOUT = "Layout";
+    String LAYOUT = "Layout";
 
     /**
      * ParentView缁勪欢鏍囪瘑
      */
-    public final static String PARENT_VIEW = "ParentView";
+    String PARENT_VIEW = "ParentView";
 
     /**
      * InnerLink缁勪欢鏍囪瘑
      */
-    public final static String INNER_LINK = "InnerLink";
+    String INNER_LINK = "InnerLink";
 
     /**
      * 鏍¢獙杩斿洖缁撴灉鐮�
      */
-    public final static String UNIQUE = "0";
-    public final static String NOT_UNIQUE = "1";
+    String UNIQUE = "0";
+    String NOT_UNIQUE = "1";
 
     /**
      * 鐢ㄦ埛鍚嶉暱搴﹂檺鍒�
      */
-    public static final int USERNAME_MIN_LENGTH = 2;
-    public static final int USERNAME_MAX_LENGTH = 20;
+    int USERNAME_MIN_LENGTH = 2;
+    int USERNAME_MAX_LENGTH = 20;
 
     /**
      * 瀵嗙爜闀垮害闄愬埗
      */
-    public static final int PASSWORD_MIN_LENGTH = 5;
-    public static final int PASSWORD_MAX_LENGTH = 20;
+    int PASSWORD_MIN_LENGTH = 5;
+    int PASSWORD_MAX_LENGTH = 20;
 }
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
new file mode 100644
index 0000000..d82779a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java
@@ -0,0 +1,93 @@
+package com.ruoyi.common.core.domain;
+
+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.utils.StringUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * 鍒嗛〉鏌ヨ瀹炰綋绫�
+ *
+ * @author Lion Li
+ */
+
+@Data
+@Accessors(chain = true)
+public class PageQuery implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+    /**
+     * 鍒嗛〉澶у皬
+     */
+    @ApiModelProperty("鍒嗛〉澶у皬")
+    private Integer pageSize;
+
+    /**
+     * 褰撳墠椤垫暟
+     */
+    @ApiModelProperty("褰撳墠椤垫暟")
+    private Integer pageNum;
+
+    /**
+     * 鎺掑簭鍒�
+     */
+    @ApiModelProperty("鎺掑簭鍒�")
+    private String orderByColumn;
+
+    /**
+     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
+     */
+    @ApiModelProperty(value = "鎺掑簭鐨勬柟鍚�", example = "asc,desc")
+    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);
+        OrderItem orderItem = buildOrderItem();
+        if (ObjectUtil.isNotNull(orderItem)) {
+            page.addOrder(orderItem);
+        }
+        return page;
+    }
+
+    private OrderItem buildOrderItem() {
+        // 鍏煎鍓嶇鎺掑簭绫诲瀷
+        if ("ascending".equals(isAsc)) {
+            isAsc = "asc";
+        } else if ("descending".equals(isAsc)) {
+            isAsc = "desc";
+        }
+        if (StringUtils.isNotBlank(orderByColumn)) {
+            String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
+            orderBy = StringUtils.toUnderScoreCase(orderBy);
+            if ("asc".equals(isAsc)) {
+                return OrderItem.asc(orderBy);
+            } else if ("desc".equals(isAsc)) {
+                return OrderItem.desc(orderBy);
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
index 30d074b..8efc9f7 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
@@ -1,5 +1,6 @@
 package com.ruoyi.common.core.domain.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.ruoyi.common.core.domain.TreeEntity;
@@ -65,6 +66,7 @@
      * 璺敱鍙傛暟
      */
 	@ApiModelProperty(value = "璺敱鍙傛暟")
+    @TableField("`query`")
     private String query;
 
 	/**
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
index 2fa57f5..dde679c 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -4,6 +4,7 @@
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.xss.Xss;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -48,15 +49,17 @@
 	 * 鐢ㄦ埛璐﹀彿
 	 */
 	@ApiModelProperty(value = "鐢ㄦ埛璐﹀彿")
-	@NotBlank(message = "鐢ㄦ埛璐﹀彿涓嶈兘涓虹┖")
+    @Xss(message = "鐢ㄦ埛璐﹀彿涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @NotBlank(message = "鐢ㄦ埛璐﹀彿涓嶈兘涓虹┖")
 	@Size(min = 0, max = 30, message = "鐢ㄦ埛璐﹀彿闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
 	private String userName;
 
 	/**
 	 * 鐢ㄦ埛鏄电О
 	 */
-	@ApiModelProperty(value = "鐢ㄦ埛鏄电О")
-	@Size(min = 0, max = 30, message = "鐢ㄦ埛鏄电О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+    @ApiModelProperty(value = "鐢ㄦ埛鏄电О")
+    @Xss(message = "鐢ㄦ埛鏄电О涓嶈兘鍖呭惈鑴氭湰瀛楃")
+    @Size(min = 0, max = 30, message = "鐢ㄦ埛鏄电О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
 	private String nickName;
 
 	/**
@@ -162,7 +165,7 @@
 	private Long[] postIds;
 
 	/**
-	 * 瑙掕壊ID
+	 * 鏁版嵁鏉冮檺 褰撳墠瑙掕壊ID
 	 */
 	@ApiModelProperty(value = "瑙掕壊ID")
 	@TableField(exist = false)
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java
index ee20abd..e11ec94 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java
@@ -1,9 +1,18 @@
 package com.ruoyi.common.core.mybatisplus.core;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.BeanCopyUtils;
 import org.apache.ibatis.annotations.Param;
 
+import java.io.Serializable;
 import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 鑷畾涔� Mapper 鎺ュ彛, 瀹炵幇 鑷畾涔夋墿灞�
@@ -18,4 +27,72 @@
 	 */
 	int insertAll(@Param("list") Collection<T> batchList);
 
+    /**
+     * 鏍规嵁 ID 鏌ヨ
+     */
+    default <V> V selectVoById(Serializable id, Class<V> voClass){
+        T obj = this.selectById(id);
+        if (ObjectUtil.isNull(obj)) {
+            return null;
+        }
+        return BeanCopyUtils.copy(obj, voClass);
+    }
+
+    /**
+     * 鏌ヨ锛堟牴鎹甀D 鎵归噺鏌ヨ锛�
+     */
+    default <V> List<V> selectVoBatchIds(Collection<? extends Serializable> idList, Class<V> voClass){
+        List<T> list = this.selectBatchIds(idList);
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+        return BeanCopyUtils.copyList(list, voClass);
+    }
+
+    /**
+     * 鏌ヨ锛堟牴鎹� columnMap 鏉′欢锛�
+     */
+    default <V> List<V> selectVoByMap(Map<String, Object> map, Class<V> voClass){
+        List<T> list = this.selectByMap(map);
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+        return BeanCopyUtils.copyList(list, voClass);
+    }
+
+    /**
+     * 鏍规嵁 entity 鏉′欢锛屾煡璇竴鏉¤褰�
+     */
+    default <V> V selectVoOne(Wrapper<T> wrapper, Class<V> voClass) {
+        T obj = this.selectOne(wrapper);
+        if (ObjectUtil.isNull(obj)) {
+            return null;
+        }
+        return BeanCopyUtils.copy(obj, voClass);
+    }
+
+    /**
+     * 鏍规嵁 entity 鏉′欢锛屾煡璇㈠叏閮ㄨ褰�
+     */
+    default <V> List<V> selectVoList(Wrapper<T> wrapper, Class<V> voClass) {
+        List<T> list = this.selectList(wrapper);
+        if (CollUtil.isEmpty(list)) {
+            return CollUtil.newArrayList();
+        }
+        return BeanCopyUtils.copyList(list, voClass);
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨVO
+     */
+    default <V, P extends IPage<V>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper, Class<V> voClass) {
+        IPage<T> pageData = this.selectPage(page, wrapper);
+        IPage<V> 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/mybatisplus/core/IServicePlus.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java
index 815791b..e645562 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java
@@ -1,7 +1,7 @@
 package com.ruoyi.common.core.mybatisplus.core;
 
-import cn.hutool.core.bean.copier.CopyOptions;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.common.core.page.PagePlus;
@@ -23,14 +23,9 @@
 
 	/**
 	 * @param id          涓婚敭id
-	 * @param copyOptions copy鏉′欢
 	 * @return V瀵硅薄
 	 */
-	V getVoById(Serializable id, CopyOptions copyOptions);
-
-	default V getVoById(Serializable id) {
-		return getVoById(id, new CopyOptions());
-	}
+	V getVoById(Serializable id);
 
 	/**
 	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
@@ -41,14 +36,9 @@
 
 	/**
 	 * @param idList      id鍒楄〃
-	 * @param copyOptions copy鏉′欢
 	 * @return V瀵硅薄
 	 */
-	List<V> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions);
-
-	default List<V> listVoByIds(Collection<? extends Serializable> idList) {
-		return listVoByIds(idList, new CopyOptions());
-	}
+	List<V> listVoByIds(Collection<? extends Serializable> idList);
 
 	/**
 	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
@@ -64,14 +54,9 @@
 
 	/**
 	 * @param columnMap   琛ㄥ瓧娈� map 瀵硅薄
-	 * @param copyOptions copy鏉′欢
 	 * @return V瀵硅薄
 	 */
-	List<V> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions);
-
-	default List<V> listVoByMap(Map<String, Object> columnMap) {
-		return listVoByMap(columnMap, new CopyOptions());
-	}
+	List<V> listVoByMap(Map<String, Object> columnMap);
 
 	/**
 	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
@@ -87,14 +72,9 @@
 
 	/**
 	 * @param queryWrapper 鏌ヨ鏉′欢
-	 * @param copyOptions  copy鏉′欢
 	 * @return V瀵硅薄
 	 */
-	V getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions);
-
-	default V getVoOne(Wrapper<T> queryWrapper) {
-		return getVoOne(queryWrapper, new CopyOptions());
-	}
+	V getVoOne(Wrapper<T> queryWrapper);
 
 	/**
 	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
@@ -105,14 +85,9 @@
 
 	/**
 	 * @param queryWrapper 鏌ヨ鏉′欢
-	 * @param copyOptions  copy鏉′欢
 	 * @return V瀵硅薄
 	 */
-	List<V> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions);
-
-	default List<V> listVo(Wrapper<T> queryWrapper) {
-		return listVo(queryWrapper, new CopyOptions());
-	}
+	List<V> listVo(Wrapper<T> queryWrapper);
 
 	/**
 	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
@@ -139,31 +114,36 @@
 	/**
 	 * @param page         鍒嗛〉瀵硅薄
 	 * @param queryWrapper 鏌ヨ鏉′欢
-	 * @param copyOptions  copy鏉′欢
 	 * @return V瀵硅薄
+     * @deprecated 3.6.0 绉婚櫎 璇蜂娇鐢� {@link ServicePlusImpl#pageVo(IPage, Wrapper)}
 	 */
-	PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper, CopyOptions copyOptions);
+    @Deprecated
+	PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper);
 
-	default PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper) {
-		return pageVo(page, queryWrapper, new CopyOptions());
-	}
-
-	/**
-	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
-	 */
+    /**
+     * @param convertor 鑷畾涔夎浆鎹㈠櫒
+     * @deprecated 3.6.0 绉婚櫎 璇蜂娇鐢� {@link ServicePlusImpl#pageVo(IPage, Wrapper)}
+     */
+    @Deprecated
 	default PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper,
 								  Function<Collection<T>, List<V>> convertor) {
 		PagePlus<T, V> result = getBaseMapper().selectPage(page, queryWrapper);
 		return result.setRecordsVo(convertor.apply(result.getRecords()));
 	}
 
+    /**
+     * @deprecated 3.6.0 绉婚櫎 璇蜂娇鐢� {@link ServicePlusImpl#pageVo(IPage, Wrapper)}
+     */
+    @Deprecated
 	default PagePlus<T, V> pageVo(PagePlus<T, V> page) {
 		return pageVo(page, Wrappers.emptyWrapper());
 	}
 
 	/**
 	 * @param convertor 鑷畾涔夎浆鎹㈠櫒
+     * @deprecated 3.6.0 绉婚櫎 璇蜂娇鐢� {@link ServicePlusImpl#pageVo(IPage, Wrapper)}
 	 */
+    @Deprecated
 	default PagePlus<T, V> pageVo(PagePlus<T, V> page, Function<Collection<T>, List<V>> convertor) {
 		return pageVo(page, Wrappers.emptyWrapper(), convertor);
 	}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java
index e9c1f19..0650cfa 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java
@@ -1,9 +1,9 @@
 package com.ruoyi.common.core.mybatisplus.core;
 
-import cn.hutool.core.bean.copier.CopyOptions;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
@@ -161,81 +161,66 @@
 
 	/**
 	 * 鏍规嵁 ID 鏌ヨ
-	 *
-	 * @param id 涓婚敭ID
 	 */
 	@Override
-	public V getVoById(Serializable id, CopyOptions copyOptions) {
-		T t = getBaseMapper().selectById(id);
-		return BeanCopyUtils.oneCopy(t, copyOptions, voClass);
+	public V getVoById(Serializable id) {
+        return getBaseMapper().selectVoById(id, voClass);
 	}
 
 	/**
 	 * 鏌ヨ锛堟牴鎹甀D 鎵归噺鏌ヨ锛�
-	 *
-	 * @param idList 涓婚敭ID鍒楄〃
 	 */
 	@Override
-	public List<V> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions) {
-		List<T> list = getBaseMapper().selectBatchIds(idList);
-		if (list == null) {
-			return null;
-		}
-		return BeanCopyUtils.listCopy(list, copyOptions, voClass);
+	public List<V> listVoByIds(Collection<? extends Serializable> idList) {
+        return getBaseMapper().selectVoBatchIds(idList, voClass);
 	}
 
 	/**
 	 * 鏌ヨ锛堟牴鎹� columnMap 鏉′欢锛�
-	 *
-	 * @param columnMap 琛ㄥ瓧娈� map 瀵硅薄
 	 */
 	@Override
-	public List<V> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions) {
-		List<T> list = getBaseMapper().selectByMap(columnMap);
-		if (list == null) {
-			return null;
-		}
-		return BeanCopyUtils.listCopy(list, copyOptions, voClass);
+	public List<V> listVoByMap(Map<String, Object> columnMap) {
+        return getBaseMapper().selectVoByMap(columnMap, voClass);
 	}
 
 	/**
 	 * 鏍规嵁 Wrapper锛屾煡璇竴鏉¤褰� <br/>
 	 * <p>缁撴灉闆嗭紝濡傛灉鏄涓細鎶涘嚭寮傚父锛岄殢鏈哄彇涓�鏉″姞涓婇檺鍒舵潯浠� wrapper.last("LIMIT 1")</p>
-	 *
-	 * @param queryWrapper 瀹炰綋瀵硅薄灏佽鎿嶄綔绫� {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
 	 */
 	@Override
-	public V getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
-		T t = getOne(queryWrapper, true);
-		return BeanCopyUtils.oneCopy(t, copyOptions, voClass);
+	public V getVoOne(Wrapper<T> queryWrapper) {
+        return getBaseMapper().selectVoOne(queryWrapper, voClass);
 	}
 
 	/**
 	 * 鏌ヨ鍒楄〃
-	 *
-	 * @param queryWrapper 瀹炰綋瀵硅薄灏佽鎿嶄綔绫� {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
 	 */
 	@Override
-	public List<V> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
-		List<T> list = getBaseMapper().selectList(queryWrapper);
-		if (list == null) {
-			return null;
-		}
-		return BeanCopyUtils.listCopy(list, copyOptions, voClass);
+	public List<V> listVo(Wrapper<T> queryWrapper) {
+        return getBaseMapper().selectVoList(queryWrapper, voClass);
 	}
 
 	/**
 	 * 缈婚〉鏌ヨ
-	 *
-	 * @param page         缈婚〉瀵硅薄
-	 * @param queryWrapper 瀹炰綋瀵硅薄灏佽鎿嶄綔绫�
+     * @deprecated 3.6.0 绉婚櫎 璇蜂娇鐢� {@link #pageVo(IPage, Wrapper)}
 	 */
 	@Override
-	public PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper, CopyOptions copyOptions) {
+    @Deprecated
+	public PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper) {
 		PagePlus<T, V> result = getBaseMapper().selectPage(page, queryWrapper);
-		List<V> volist = BeanCopyUtils.listCopy(result.getRecords(), copyOptions, voClass);
+		List<V> volist = BeanCopyUtils.copyList(result.getRecords(), voClass);
 		result.setRecordsVo(volist);
 		return result;
 	}
 
+    /**
+     * 缈婚〉鏌ヨ
+     *
+     * @param page         缈婚〉瀵硅薄
+     * @param queryWrapper 瀹炰綋瀵硅薄灏佽鎿嶄綔绫�
+     */
+    public <P extends IPage<V>> P pageVo(IPage<T> page, Wrapper<T> queryWrapper) {
+        return getBaseMapper().selectVoPage(page, queryWrapper, voClass);
+    }
+
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PagePlus.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PagePlus.java
index 79d889c..bff381c 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PagePlus.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PagePlus.java
@@ -16,9 +16,11 @@
  * @param <T> 鏁版嵁搴撳疄浣�
  * @param <K> vo瀹炰綋
  * @author Lion Li
+ * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link com.ruoyi.common.core.domain.PageQuery#build()}
  */
 @Data
 @Accessors(chain = true)
+@Deprecated
 public class PagePlus<T,K> implements IPage<T> {
 
     /**
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
index 81c596b..46b01b9 100644
--- 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
@@ -1,5 +1,7 @@
 package com.ruoyi.common.core.page;
 
+import cn.hutool.http.HttpStatus;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -57,4 +59,29 @@
 		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/DataScopeType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java
new file mode 100644
index 0000000..7cf3d5e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataScopeType.java
@@ -0,0 +1,72 @@
+package com.ruoyi.common.enums;
+
+import com.ruoyi.common.utils.StringUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 鏁版嵁鏉冮檺绫诲瀷
+ *
+ * 璇硶鏀寔 spel 妯℃澘琛ㄨ揪寮�
+ *
+ * 鍐呯疆鏁版嵁 user 褰撳墠鐢ㄦ埛 鍐呭鍙傝�� SysUser
+ * 濡傞渶鎵╁睍鏁版嵁 鍙娇鐢� {@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/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
index d6fe728..afa4e14 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
@@ -7,8 +7,10 @@
  * 鏁版嵁婧�
  *
  * @author Lion Li
+ * @deprecated 3.6.0 绉婚櫎
  */
 @AllArgsConstructor
+@Deprecated
 public enum DataSourceType {
     /**
      * 涓诲簱
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
index f626a5e..9936f67 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java
@@ -5,7 +5,7 @@
 import com.alibaba.excel.event.AnalysisEventListener;
 import com.alibaba.excel.exception.ExcelAnalysisException;
 import com.alibaba.excel.exception.ExcelDataConvertException;
-import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.utils.JsonUtils;
 import com.ruoyi.common.utils.ValidatorUtils;
 import lombok.NoArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -84,7 +84,7 @@
     @Override
     public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
         this.headMap = headMap;
-        log.debug("瑙f瀽鍒颁竴鏉¤〃澶存暟鎹�: {}", JSON.toJSONString(headMap));
+        log.debug("瑙f瀽鍒颁竴鏉¤〃澶存暟鎹�: {}", JsonUtils.toJsonString(headMap));
     }
 
     @Override
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
index 9040485..2345c20 100644
--- 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
@@ -9,6 +9,6 @@
     private static final long serialVersionUID = 1L;
 
     public CaptchaException() {
-        super("user.jcaptcha.error", null);
+        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
index ae5f759..bb4c037 100644
--- 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
@@ -9,6 +9,6 @@
     private static final long serialVersionUID = 1L;
 
     public CaptchaExpireException() {
-        super("user.jcaptcha.expire", null);
+        super("user.jcaptcha.expire");
     }
 }
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
index 0fab116..863ba76 100644
--- 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
@@ -9,6 +9,6 @@
     private static final long serialVersionUID = 1L;
 
     public UserPasswordNotMatchException() {
-        super("user.password.not.match", null);
+        super("user.password.not.match");
     }
 }
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
new file mode 100644
index 0000000..96f5425
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataPermissionHelper.java
@@ -0,0 +1,45 @@
+package com.ruoyi.common.helper;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.utils.ServletUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 鏁版嵁鏉冮檺鍔╂墜
+ *
+ * @author Lion Li
+ * @version 3.5.0
+ */
+@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() {
+        HttpServletRequest request = ServletUtils.getRequest();
+        Object attribute = request.getAttribute(DATA_PERMISSION_KEY);
+        if (ObjectUtil.isNull(attribute)) {
+            request.setAttribute(DATA_PERMISSION_KEY, new HashMap<>());
+            attribute = request.getAttribute(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/utils/BeanCopyUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java
index 8bf40d1..0bd4a55 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java
@@ -1,66 +1,120 @@
 package com.ruoyi.common.utils;
 
-import cn.hutool.core.bean.copier.BeanCopier;
-import cn.hutool.core.bean.copier.CopyOptions;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.extra.cglib.CglibUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import java.util.List;
-import java.util.stream.Collectors;
+import java.util.Map;
 
 /**
- * bean娣辨嫹璐濆伐鍏�
+ * bean娣辨嫹璐濆伐鍏�(鍩轰簬 cglib 鎬ц兘浼樺紓)
  *
  * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class BeanCopyUtils {
 
     /**
      * 鍗曞璞″熀浜巆lass鍒涘缓鎷疯礉
      *
-     * @param source      鏁版嵁鏉ユ簮瀹炰綋
-     * @param copyOptions copy鏉′欢
-     * @param desc        鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
+     * @param source 鏁版嵁鏉ユ簮瀹炰綋
+     * @param desc   鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
      * @return desc
      */
-    public static <T, V> V oneCopy(T source, CopyOptions copyOptions, Class<V> desc) {
-        V v = ReflectUtil.newInstanceIfPossible(desc);
-        return oneCopy(source, copyOptions, v);
+    public static <T, V> V copy(T source, Class<V> desc) {
+        if (ObjectUtil.isNull(source)) {
+            return null;
+        }
+        if (ObjectUtil.isNull(desc)) {
+            return null;
+        }
+        return CglibUtil.copy(source, desc);
     }
 
     /**
      * 鍗曞璞″熀浜庡璞″垱寤烘嫹璐�
      *
-     * @param source      鏁版嵁鏉ユ簮瀹炰綋
-     * @param copyOptions copy鏉′欢
-     * @param desc        杞崲鍚庣殑瀵硅薄
+     * @param source 鏁版嵁鏉ユ簮瀹炰綋
+     * @param desc   杞崲鍚庣殑瀵硅薄
      * @return desc
      */
-    public static <T, V> V oneCopy(T source, CopyOptions copyOptions, V desc) {
+    public static <T, V> V copy(T source, V desc) {
         if (ObjectUtil.isNull(source)) {
             return null;
         }
-        return BeanCopier.create(source, desc, copyOptions).copy();
+        if (ObjectUtil.isNull(desc)) {
+            return null;
+        }
+        CglibUtil.copy(source, desc);
+        return desc;
     }
 
     /**
      * 鍒楄〃瀵硅薄鍩轰簬class鍒涘缓鎷疯礉
      *
-     * @param sourceList  鏁版嵁鏉ユ簮瀹炰綋鍒楄〃
-     * @param copyOptions copy鏉′欢
-     * @param desc        鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
+     * @param sourceList 鏁版嵁鏉ユ簮瀹炰綋鍒楄〃
+     * @param desc       鎻忚堪瀵硅薄 杞崲鍚庣殑瀵硅薄
      * @return desc
      */
-    public static <T, V> List<V> listCopy(List<T> sourceList, CopyOptions copyOptions, Class<V> 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 sourceList.stream()
-                .map(source -> oneCopy(source, copyOptions, desc))
-                .collect(Collectors.toList());
+        return CglibUtil.copyList(sourceList, () -> ReflectUtil.newInstanceIfPossible(desc));
+    }
+
+    /**
+     * bean鎷疯礉鍒癿ap
+     *
+     * @param bean 鏁版嵁鏉ユ簮瀹炰綋
+     * @return map瀵硅薄
+     */
+    public static <T> Map<String, Object> copyToMap(T bean) {
+        if (ObjectUtil.isNull(bean)) {
+            return null;
+        }
+        return CglibUtil.toMap(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;
+        }
+        return CglibUtil.toBean(map, beanClass);
+    }
+
+    /**
+     * 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;
+        }
+        return CglibUtil.fillBean(map, bean);
     }
 }
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
index 1e27f24..bc38eed 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -1,5 +1,7 @@
 package com.ruoyi.common.utils;
 
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 import org.apache.commons.lang3.time.DateFormatUtils;
 
 import java.lang.management.ManagementFactory;
@@ -12,6 +14,7 @@
  *
  * @author ruoyi
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
 
     public static String YYYY = "yyyy";
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
deleted file mode 100644
index 3309da1..0000000
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package com.ruoyi.common.utils;
-
-import cn.hutool.core.collection.CollUtil;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.core.domain.entity.SysDictData;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 瀛楀吀宸ュ叿绫�
- *
- * @author ruoyi
- * @deprecated 3.5.0 鐗堟湰鍒犻櫎 杩佺Щ鑷� {@link com.ruoyi.common.core.service.DictService}
- */
-@Deprecated
-public class DictUtils {
-
-    /**
-     * 鍒嗛殧绗�
-     */
-    public static final String SEPARATOR = ",";
-
-    /**
-     * 璁剧疆瀛楀吀缂撳瓨
-     *
-     * @param key       鍙傛暟閿�
-     * @param dictDatas 瀛楀吀鏁版嵁鍒楄〃
-     */
-    public static void setDictCache(String key, List<SysDictData> dictDatas) {
-        RedisUtils.setCacheObject(getCacheKey(key), dictDatas);
-    }
-
-    /**
-     * 鑾峰彇瀛楀吀缂撳瓨
-     *
-     * @param key 鍙傛暟閿�
-     * @return dictDatas 瀛楀吀鏁版嵁鍒楄〃
-     */
-    public static List<SysDictData> getDictCache(String key) {
-        List<SysDictData> dictDatas = RedisUtils.getCacheObject(getCacheKey(key));
-        if (StringUtils.isNotNull(dictDatas)) {
-            return dictDatas;
-        }
-        return null;
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictValue 瀛楀吀鍊�
-     * @return 瀛楀吀鏍囩
-     */
-    public static String getDictLabel(String dictType, String dictValue) {
-        return getDictLabel(dictType, dictValue, SEPARATOR);
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictLabel 瀛楀吀鏍囩
-     * @return 瀛楀吀鍊�
-     */
-    public static String getDictValue(String dictType, String dictLabel) {
-        return getDictValue(dictType, dictLabel, SEPARATOR);
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictValue 瀛楀吀鍊�
-     * @param separator 鍒嗛殧绗�
-     * @return 瀛楀吀鏍囩
-     */
-    public static String getDictLabel(String dictType, String dictValue, String separator) {
-        StringBuilder propertyString = new StringBuilder();
-        List<SysDictData> datas = getDictCache(dictType);
-
-        if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) {
-            for (SysDictData dict : datas) {
-                for (String value : dictValue.split(separator)) {
-                    if (value.equals(dict.getDictValue())) {
-                        propertyString.append(dict.getDictLabel() + separator);
-                        break;
-                    }
-                }
-            }
-        } else {
-            for (SysDictData dict : datas) {
-                if (dictValue.equals(dict.getDictValue())) {
-                    return dict.getDictLabel();
-                }
-            }
-        }
-        return StringUtils.stripEnd(propertyString.toString(), separator);
-    }
-
-    /**
-     * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
-     *
-     * @param dictType  瀛楀吀绫诲瀷
-     * @param dictLabel 瀛楀吀鏍囩
-     * @param separator 鍒嗛殧绗�
-     * @return 瀛楀吀鍊�
-     */
-    public static String getDictValue(String dictType, String dictLabel, String separator) {
-        StringBuilder propertyString = new StringBuilder();
-        List<SysDictData> datas = getDictCache(dictType);
-
-        if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) {
-            for (SysDictData dict : datas) {
-                for (String label : dictLabel.split(separator)) {
-                    if (label.equals(dict.getDictLabel())) {
-                        propertyString.append(dict.getDictValue() + separator);
-                        break;
-                    }
-                }
-            }
-        } else {
-            for (SysDictData dict : datas) {
-                if (dictLabel.equals(dict.getDictLabel())) {
-                    return dict.getDictValue();
-                }
-            }
-        }
-        return StringUtils.stripEnd(propertyString.toString(), separator);
-    }
-
-    /**
-     * 鍒犻櫎鎸囧畾瀛楀吀缂撳瓨
-     *
-     * @param key 瀛楀吀閿�
-     */
-    public static void removeDictCache(String key) {
-        RedisUtils.deleteObject(getCacheKey(key));
-    }
-
-    /**
-     * 娓呯┖瀛楀吀缂撳瓨
-     */
-    public static void clearDictCache() {
-        Collection<String> keys = RedisUtils.keys(Constants.SYS_DICT_KEY + "*");
-        RedisUtils.deleteObject(keys);
-    }
-
-    /**
-     * 璁剧疆cache key
-     *
-     * @param configKey 鍙傛暟閿�
-     * @return 缂撳瓨閿甼ey
-     */
-    public static String getCacheKey(String configKey) {
-        return Constants.SYS_DICT_KEY + configKey;
-    }
-}
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
index b65c23d..1c01912 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java
@@ -21,14 +21,18 @@
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class JsonUtils {
 
-    private static ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class);
+    private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class);
+
+    public static ObjectMapper getObjectMapper() {
+        return OBJECT_MAPPER;
+    }
 
     public static String toJsonString(Object object) {
         if (StringUtils.isNull(object)) {
             return null;
         }
         try {
-            return objectMapper.writeValueAsString(object);
+            return OBJECT_MAPPER.writeValueAsString(object);
         } catch (JsonProcessingException e) {
             throw new RuntimeException(e);
         }
@@ -39,7 +43,7 @@
             return null;
         }
         try {
-            return objectMapper.readValue(text, clazz);
+            return OBJECT_MAPPER.readValue(text, clazz);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -50,7 +54,7 @@
             return null;
         }
         try {
-            return objectMapper.readValue(bytes, clazz);
+            return OBJECT_MAPPER.readValue(bytes, clazz);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -61,7 +65,7 @@
             return null;
         }
         try {
-            return objectMapper.readValue(text, typeReference);
+            return OBJECT_MAPPER.readValue(text, typeReference);
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -72,7 +76,7 @@
             return null;
         }
         try {
-            return objectMapper.readValue(text, new TypeReference<Map<String, T>>() {
+            return OBJECT_MAPPER.readValue(text, new TypeReference<Map<String, T>>() {
             });
         } catch (IOException e) {
             throw new RuntimeException(e);
@@ -84,7 +88,7 @@
             return new ArrayList<>();
         }
         try {
-            return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
+            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
index 039eb24..c9c091d 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
@@ -1,15 +1,21 @@
 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 ruoyi
+ * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class MessageUtils {
+
+    private static final MessageSource MESSAGE_SOURCE = SpringUtils.getBean(MessageSource.class);
+
     /**
      * 鏍规嵁娑堟伅閿拰鍙傛暟 鑾峰彇娑堟伅 濮旀墭缁檚pring messageSource
      *
@@ -18,7 +24,6 @@
      * @return 鑾峰彇鍥介檯鍖栫炕璇戝��
      */
     public static String message(String code, Object... args) {
-        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
-        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+        return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
     }
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
index abc42dd..5042de4 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
@@ -2,11 +2,15 @@
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.http.HttpStatus;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.OrderItem;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.utils.sql.SqlUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import java.util.List;
 
@@ -14,37 +18,46 @@
  * 鍒嗛〉宸ュ叿
  *
  * @author Lion Li
+ * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link PageQuery} 涓� {@link TableDataInfo}
  */
+@Deprecated
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class PageUtils {
 
     /**
      * 褰撳墠璁板綍璧峰绱㈠紩
      */
+    @Deprecated
     public static final String PAGE_NUM = "pageNum";
 
     /**
      * 姣忛〉鏄剧ず璁板綍鏁�
      */
+    @Deprecated
     public static final String PAGE_SIZE = "pageSize";
 
     /**
      * 鎺掑簭鍒�
      */
+    @Deprecated
     public static final String ORDER_BY_COLUMN = "orderByColumn";
 
     /**
      * 鎺掑簭鐨勬柟鍚� "desc" 鎴栬�� "asc".
      */
+    @Deprecated
     public static final String IS_ASC = "isAsc";
 
     /**
      * 褰撳墠璁板綍璧峰绱㈠紩 榛樿鍊�
      */
+    @Deprecated
     public static final int DEFAULT_PAGE_NUM = 1;
 
     /**
      * 姣忛〉鏄剧ず璁板綍鏁� 榛樿鍊� 榛樿鏌ュ叏閮�
      */
+    @Deprecated
     public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
 
     /**
@@ -53,7 +66,10 @@
      * @param <T> domain 瀹炰綋
      * @param <K> vo 瀹炰綋
      * @return 鍒嗛〉瀵硅薄
+     * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link PageQuery#build()}
+     * 鐢变簬浣跨敤 Servlet 鑾峰彇鍙兘浠� param 鑾峰彇 鐏垫椿鎬ч檷浣� 鏁呭皢浼犲弬鎿嶄綔浜ょ粰鐢ㄦ埛
      */
+    @Deprecated
     public static <T, K> PagePlus<T, K> buildPagePlus() {
         Integer pageNum = ServletUtils.getParameterToInt(PAGE_NUM, DEFAULT_PAGE_NUM);
         Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE);
@@ -70,6 +86,7 @@
         return page;
     }
 
+    @Deprecated
     public static <T> Page<T> buildPage() {
         return buildPage(null, null);
     }
@@ -79,7 +96,10 @@
      *
      * @param <T> domain 瀹炰綋
      * @return 鍒嗛〉瀵硅薄
+     * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link PageQuery#build()}
+     * 鐢变簬浣跨敤 Servlet 鑾峰彇鍙兘浠� param 鑾峰彇 鐏垫椿鎬ч檷浣� 鏁呭皢浼犲弬鎿嶄綔浜ょ粰鐢ㄦ埛
      */
+    @Deprecated
     public static <T> Page<T> buildPage(String defaultOrderByColumn, String defaultIsAsc) {
         Integer pageNum = ServletUtils.getParameterToInt(PAGE_NUM, DEFAULT_PAGE_NUM);
         Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE);
@@ -115,6 +135,15 @@
         return null;
     }
 
+    /**
+     * 鏋勫缓 MP 鏅�氬垎椤靛璞�
+     *
+     * @param <T> domain 瀹炰綋
+     * @return 鍒嗛〉瀵硅薄
+     * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link PageQuery#build()}
+     * 鐢变簬浣跨敤 Servlet 鑾峰彇鍙兘浠� param 鑾峰彇 鐏垫椿鎬ч檷浣� 鏁呭皢浼犲弬鎿嶄綔浜ょ粰鐢ㄦ埛
+     */
+    @Deprecated
     public static <T, K> TableDataInfo<K> buildDataInfo(PagePlus<T, K> page) {
         TableDataInfo<K> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
@@ -124,6 +153,10 @@
         return rspData;
     }
 
+    /**
+     * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link TableDataInfo#build(IPage)}
+     */
+    @Deprecated
     public static <T> TableDataInfo<T> buildDataInfo(Page<T> page) {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
@@ -133,6 +166,10 @@
         return rspData;
     }
 
+    /**
+     * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link TableDataInfo#build(List)}
+     */
+    @Deprecated
     public static <T> TableDataInfo<T> buildDataInfo(List<T> list) {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
@@ -142,6 +179,10 @@
         return rspData;
     }
 
+    /**
+     * @deprecated 3.6.0 鍒犻櫎 璇蜂娇鐢� {@link TableDataInfo#build()}
+     */
+    @Deprecated
     public static <T> TableDataInfo<T> buildDataInfo() {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java
index 7f4d2ca..0ccbe0f 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java
@@ -1,6 +1,6 @@
 package com.ruoyi.common.utils;
 
-import com.google.common.collect.Lists;
+import cn.hutool.core.collection.IterUtil;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
@@ -23,7 +23,7 @@
 @SuppressWarnings(value = {"unchecked", "rawtypes"})
 public class RedisUtils {
 
-    private static RedissonClient client = SpringUtils.getBean(RedissonClient.class);
+    private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
 
     /**
      * 闄愭祦
@@ -35,7 +35,7 @@
      * @return -1 琛ㄧず澶辫触
      */
     public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
-        RRateLimiter rateLimiter = client.getRateLimiter(key);
+        RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
         rateLimiter.trySetRate(rateType, rate, rateInterval, RateIntervalUnit.SECONDS);
         if (rateLimiter.tryAcquire()) {
             return rateLimiter.availablePermits();
@@ -45,10 +45,10 @@
     }
 
     /**
-     * 鑾峰彇瀹炰緥id
+     * 鑾峰彇瀹㈡埛绔疄渚�
      */
-    public static String getClientId() {
-        return client.getId();
+    public static RedissonClient getClient() {
+        return CLIENT;
     }
 
     /**
@@ -59,13 +59,13 @@
      * @param consumer   鑷畾涔夊鐞�
      */
     public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
-        RTopic topic = client.getTopic(channelKey);
+        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);
+        RTopic topic = CLIENT.getTopic(channelKey);
         topic.publish(msg);
     }
 
@@ -77,7 +77,7 @@
      * @param consumer   鑷畾涔夊鐞�
      */
     public static <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
-        RTopic topic = client.getTopic(channelKey);
+        RTopic topic = CLIENT.getTopic(channelKey);
         topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
     }
 
@@ -94,13 +94,13 @@
     /**
      * 缂撳瓨鍩烘湰鐨勫璞★紝淇濈暀褰撳墠瀵硅薄 TTL 鏈夋晥鏈�
      *
-     * @param key   缂撳瓨鐨勯敭鍊�
-     * @param value 缂撳瓨鐨勫��
+     * @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<Object> bucket = client.getBucket(key);
+        RBucket<Object> bucket = CLIENT.getBucket(key);
         if (isSaveTtl) {
             try {
                 bucket.setAndKeepTTL(value);
@@ -123,9 +123,22 @@
      * @param timeUnit 鏃堕棿棰楃矑搴�
      */
     public static <T> void setCacheObject(final String key, final T value, final long timeout, final TimeUnit timeUnit) {
-        RBucket<T> result = client.getBucket(key);
+        RBucket<T> result = CLIENT.getBucket(key);
         result.set(value);
         result.expire(timeout, timeUnit);
+    }
+
+    /**
+     * 娉ㄥ唽瀵硅薄鐩戝惉鍣�
+     *
+     * 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);
     }
 
     /**
@@ -148,7 +161,7 @@
      * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
      */
     public static boolean expire(final String key, final long timeout, final TimeUnit unit) {
-        RBucket rBucket = client.getBucket(key);
+        RBucket rBucket = CLIENT.getBucket(key);
         return rBucket.expire(timeout, unit);
     }
 
@@ -159,7 +172,7 @@
      * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
      */
     public static <T> T getCacheObject(final String key) {
-        RBucket<T> rBucket = client.getBucket(key);
+        RBucket<T> rBucket = CLIENT.getBucket(key);
         return rBucket.get();
     }
 
@@ -170,29 +183,26 @@
      * @return 鍓╀綑瀛樻椿鏃堕棿
      */
     public static <T> long getTimeToLive(final String key) {
-        RBucket<T> rBucket = client.getBucket(key);
+        RBucket<T> rBucket = CLIENT.getBucket(key);
         return rBucket.remainTimeToLive();
     }
 
     /**
      * 鍒犻櫎鍗曚釜瀵硅薄
      *
-     * @param key
+     * @param key 缂撳瓨鐨勯敭鍊�
      */
     public static boolean deleteObject(final String key) {
-        return client.getBucket(key).delete();
+        return CLIENT.getBucket(key).delete();
     }
-
-    /* */
 
     /**
      * 鍒犻櫎闆嗗悎瀵硅薄
      *
      * @param collection 澶氫釜瀵硅薄
-     * @return
      */
     public static void deleteObject(final Collection collection) {
-        RBatch batch = client.createBatch();
+        RBatch batch = CLIENT.createBatch();
         collection.forEach(t -> {
             batch.getBucket(t.toString()).deleteAsync();
         });
@@ -207,8 +217,21 @@
      * @return 缂撳瓨鐨勫璞�
      */
     public static <T> boolean setCacheList(final String key, final List<T> dataList) {
-        RList<T> rList = client.getList(key);
+        RList<T> rList = CLIENT.getList(key);
         return rList.addAll(dataList);
+    }
+
+    /**
+     * 娉ㄥ唽List鐩戝惉鍣�
+     *
+     * 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);
     }
 
     /**
@@ -218,7 +241,7 @@
      * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
      */
     public static <T> List<T> getCacheList(final String key) {
-        RList<T> rList = client.getList(key);
+        RList<T> rList = CLIENT.getList(key);
         return rList.readAll();
     }
 
@@ -230,42 +253,68 @@
      * @return 缂撳瓨鏁版嵁鐨勫璞�
      */
     public static <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
-        RSet<T> rSet = client.getSet(key);
+        RSet<T> rSet = CLIENT.getSet(key);
         return rSet.addAll(dataSet);
+    }
+
+    /**
+     * 娉ㄥ唽Set鐩戝惉鍣�
+     *
+     * 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
-     * @return
+     * @param key 缂撳瓨鐨刱ey
+     * @return set瀵硅薄
      */
     public static <T> Set<T> getCacheSet(final String key) {
-        RSet<T> rSet = client.getSet(key);
+        RSet<T> rSet = CLIENT.getSet(key);
         return rSet.readAll();
     }
 
     /**
      * 缂撳瓨Map
      *
-     * @param key
-     * @param dataMap
+     * @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<String, T> rMap = CLIENT.getMap(key);
             rMap.putAll(dataMap);
         }
     }
 
     /**
+     * 娉ㄥ唽Map鐩戝惉鍣�
+     *
+     * 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
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return map瀵硅薄
      */
     public static <T> Map<String, T> getCacheMap(final String key) {
-        RMap<String, T> rMap = client.getMap(key);
+        RMap<String, T> rMap = CLIENT.getMap(key);
         return rMap.getAll(rMap.keySet());
     }
 
@@ -277,7 +326,7 @@
      * @param value 鍊�
      */
     public static <T> void setCacheMapValue(final String key, final String hKey, final T value) {
-        RMap<String, T> rMap = client.getMap(key);
+        RMap<String, T> rMap = CLIENT.getMap(key);
         rMap.put(hKey, value);
     }
 
@@ -289,7 +338,7 @@
      * @return Hash涓殑瀵硅薄
      */
     public static <T> T getCacheMapValue(final String key, final String hKey) {
-        RMap<String, T> rMap = client.getMap(key);
+        RMap<String, T> rMap = CLIENT.getMap(key);
         return rMap.get(hKey);
     }
 
@@ -301,7 +350,7 @@
      * @return Hash涓殑瀵硅薄
      */
     public static <T> T delCacheMapValue(final String key, final String hKey) {
-        RMap<String, T> rMap = client.getMap(key);
+        RMap<String, T> rMap = CLIENT.getMap(key);
         return rMap.remove(hKey);
     }
 
@@ -313,7 +362,7 @@
      * @return Hash瀵硅薄闆嗗悎
      */
     public static <K, V> Map<K, V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
-        RMap<K, V> rMap = client.getMap(key);
+        RMap<K, V> rMap = CLIENT.getMap(key);
         return rMap.getAll(hKeys);
     }
 
@@ -324,7 +373,7 @@
      * @return 瀵硅薄鍒楄〃
      */
     public static Collection<String> keys(final String pattern) {
-        Iterable<String> iterable = client.getKeys().getKeysByPattern(pattern);
-        return Lists.newArrayList(iterable);
+        Iterable<String> iterable = CLIENT.getKeys().getKeysByPattern(pattern);
+        return IterUtil.toList(iterable);
     }
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
index 4112748..ccbd302 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
@@ -5,6 +5,10 @@
 import com.ruoyi.common.core.service.UserService;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 
 /**
@@ -12,6 +16,7 @@
  *
  * @author Long Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class SecurityUtils {
 
     /**
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
index 1e1db37..5babaeb 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
@@ -3,6 +3,8 @@
 import cn.hutool.core.convert.Convert;
 import cn.hutool.extra.servlet.ServletUtil;
 import cn.hutool.http.HttpStatus;
+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;
@@ -19,6 +21,7 @@
  *
  * @author ruoyi
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class ServletUtils extends ServletUtil {
 
     /**
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
index 12fc4db..f96c1e5 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
@@ -7,6 +7,8 @@
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import java.util.*;
 
@@ -15,6 +17,7 @@
  *
  * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class StringUtils extends org.apache.commons.lang3.StringUtils {
 
 	/**
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
index 5be9582..1952929 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
@@ -1,7 +1,8 @@
 package com.ruoyi.common.utils;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 
 import java.util.concurrent.*;
 
@@ -10,8 +11,9 @@
  *
  * @author ruoyi
  */
+@Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class Threads {
-    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
 
     /**
      * sleep绛夊緟,鍗曚綅涓烘绉�
@@ -38,7 +40,7 @@
                 if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                     pool.shutdownNow();
                     if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
-                        logger.info("Pool did not terminate");
+                        log.info("Pool did not terminate");
                     }
                 }
             } catch (InterruptedException ie) {
@@ -67,7 +69,7 @@
             }
         }
         if (t != null) {
-            logger.error(t.getMessage(), t);
+            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
index a8380a2..76bf864 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeBuildUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeBuildUtils.java
@@ -4,6 +4,8 @@
 import cn.hutool.core.lang.tree.TreeNodeConfig;
 import cn.hutool.core.lang.tree.TreeUtil;
 import cn.hutool.core.lang.tree.parser.NodeParser;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import java.util.List;
 
@@ -12,6 +14,7 @@
  *
  * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class TreeBuildUtils extends TreeUtil {
 
     /**
@@ -19,13 +22,8 @@
      */
     public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
 
-    /**
-     * 榛樿鏍戠埗鑺傜偣id
-     */
-    public static final Long DEFAULT_PARENT_ID = 0L;
-
-    public static <T> List<Tree<Long>> build(List<T> list, NodeParser<T, Long> nodeParser) {
-        return TreeUtil.build(list, DEFAULT_PARENT_ID, DEFAULT_CONFIG, nodeParser);
+    public static <T> List<Tree<Long>> build(List<T> list, Long parentId, NodeParser<T, Long> nodeParser) {
+        return TreeUtil.build(list, parentId, 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
index c28cf80..522b989 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ValidatorUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ValidatorUtils.java
@@ -1,8 +1,11 @@
 package com.ruoyi.common.utils;
 
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
 import javax.validation.ConstraintViolation;
 import javax.validation.ConstraintViolationException;
-import javax.validation.Validation;
 import javax.validation.Validator;
 import java.util.Set;
 
@@ -11,9 +14,10 @@
  *
  * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class ValidatorUtils {
 
-	private static final Validator VALID = Validation.buildDefaultValidatorFactory().getValidator();
+	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);
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
index ff56a2a..5118d51 100644
--- 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
@@ -1,6 +1,8 @@
 package com.ruoyi.common.utils.file;
 
 import cn.hutool.core.io.FileUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.UnsupportedEncodingException;
@@ -12,6 +14,7 @@
  *
  * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class FileUtils extends FileUtil {
 
     /**
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
index 808cc8d..b519226 100644
--- 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
@@ -7,6 +7,8 @@
 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;
 
 import java.util.Map;
@@ -17,6 +19,7 @@
  * @author Lion Li
  */
 @Slf4j
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class AddressUtils {
 
     // IP鍦板潃鏌ヨ
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
index 6c5dc5f..36dc67f 100644
--- 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
@@ -9,6 +9,8 @@
 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 javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
@@ -21,6 +23,7 @@
  *
  * @author Lion Li
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class ExcelUtil {
 
     /**
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
index 07ac943..0e0d7e7 100644
--- 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
@@ -2,6 +2,8 @@
 
 import cn.hutool.core.util.ReflectUtil;
 import com.ruoyi.common.utils.StringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import java.lang.reflect.Method;
 
@@ -11,6 +13,7 @@
  * @author Lion Li
  */
 @SuppressWarnings("rawtypes")
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class ReflectUtils extends ReflectUtil {
 
     private static final String SETTER_PREFIX = "set";
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
index 8121e02..5829a1e 100644
--- 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
@@ -2,17 +2,26 @@
 
 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 String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
+
     /**
      * 浠呮敮鎸佸瓧姣嶃�佹暟瀛椼�佷笅鍒掔嚎銆佺┖鏍笺�侀�楀彿銆佸皬鏁扮偣锛堟敮鎸佸涓瓧娈垫帓搴忥級
      */
-    public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+    public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
 
     /**
      * 妫�鏌ュ瓧绗︼紝闃叉娉ㄥ叆缁曡繃
@@ -30,4 +39,19 @@
     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
new file mode 100644
index 0000000..0a26d60
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.xss;
+
+import javax.validation.Constraint;
+import javax.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
new file mode 100644
index 0000000..03102df
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
@@ -0,0 +1,21 @@
+package com.ruoyi.common.xss;
+
+import cn.hutool.core.util.ReUtil;
+import cn.hutool.http.HtmlUtil;
+
+import javax.validation.ConstraintValidator;
+import javax.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/src/main/java/com/ruoyi/demo/controller/TestBatchController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
index d6e691d..54cd448 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
@@ -33,10 +33,12 @@
 
     /**
      * 鏂板鎵归噺鏂规硶 鍙畬缇庢浛浠� saveBatch 绉掔骇鎻掑叆涓婁竾鏁版嵁 (瀵筸ysql璐熻嵎杈冨ぇ)
+     *
+     * 3.5.0 鐗堟湰 澧炲姞 rewriteBatchedStatements=true 鎵瑰鐞嗗弬鏁� 浣� MP 鍘熺敓鎵瑰鐞嗗彲浠ヨ揪鍒板悓鏍风殑閫熷害
      */
     @ApiOperation(value = "鏂板鎵归噺鏂规硶")
     @PostMapping("/add")
-//	@DataSource(DataSourceType.SLAVE)
+//	@DS("slave")
     public AjaxResult<Void> add() {
         List<TestDemo> list = new ArrayList<>();
         for (int i = 0; i < 1000; i++) {
@@ -47,10 +49,12 @@
 
     /**
      * 鏂板鎴栨洿鏂� 鍙畬缇庢浛浠� saveOrUpdateBatch 楂樻�ц兘
+     *
+     * 3.5.0 鐗堟湰 澧炲姞 rewriteBatchedStatements=true 鎵瑰鐞嗗弬鏁� 浣� MP 鍘熺敓鎵瑰鐞嗗彲浠ヨ揪鍒板悓鏍风殑閫熷害
      */
     @ApiOperation(value = "鏂板鎴栨洿鏂版壒閲忔柟娉�")
     @PostMapping("/addOrUpdate")
-//	@DataSource(DataSourceType.SLAVE)
+//	@DS("slave")
     public AjaxResult<Void> addOrUpdate() {
         List<TestDemo> list = new ArrayList<>();
         for (int i = 0; i < 1000; i++) {
@@ -72,7 +76,7 @@
      */
     @ApiOperation(value = "鍒犻櫎鎵归噺鏂规硶")
     @DeleteMapping()
-//	@DataSource(DataSourceType.SLAVE)
+//	@DS("slave")
     public AjaxResult<Void> remove() {
         return toAjax(iTestDemoService.remove(new LambdaQueryWrapper<TestDemo>()
             .eq(TestDemo::getOrderNum, -1L)) ? 1 : 0);
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
index 6837452..2ec2342 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
@@ -6,6 +6,7 @@
 import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
@@ -54,8 +55,8 @@
     @ApiOperation("鏌ヨ娴嬭瘯鍗曡〃鍒楄〃")
     @SaCheckPermission("demo:demo:list")
     @GetMapping("/list")
-    public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo) {
-        return iTestDemoService.queryPageList(bo);
+    public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) {
+        return iTestDemoService.queryPageList(bo, pageQuery);
     }
 
 	/**
@@ -65,7 +66,7 @@
 	@SaCheckPermission("demo:demo:list")
 	@GetMapping("/page")
 	public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo) {
-		return iTestDemoService.customPageList(bo);
+		return iTestDemoService.customPageList(bo, pageQuery);
 	}
 
     @ApiOperation("瀵煎叆娴嬭瘯-鏍¢獙")
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
index 46018b1..63d2836 100644
--- 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
@@ -1,16 +1,15 @@
 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 io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
-import javax.validation.constraints.*;
 
-import java.util.Date;
-
-import com.ruoyi.common.core.domain.BaseEntity;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
 
 /**
  * 娴嬭瘯鍗曡〃涓氬姟瀵硅薄 test_demo
@@ -65,30 +64,5 @@
 	@ApiModelProperty("鍊�")
     @NotBlank(message = "鍊间笉鑳戒负绌�", groups = { AddGroup.class, EditGroup.class })
     private String value;
-
-
-    /**
-     * 鍒嗛〉澶у皬
-     */
-    @ApiModelProperty("鍒嗛〉澶у皬")
-    private Integer pageSize;
-
-    /**
-     * 褰撳墠椤垫暟
-     */
-    @ApiModelProperty("褰撳墠椤垫暟")
-    private Integer pageNum;
-
-    /**
-     * 鎺掑簭鍒�
-     */
-    @ApiModelProperty("鎺掑簭鍒�")
-    private String orderByColumn;
-
-    /**
-     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
-     */
-    @ApiModelProperty(value = "鎺掑簭鐨勬柟鍚�", example = "asc,desc")
-    private String isAsc;
 
 }
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
index 2dfe1ff..c561dd7 100644
--- 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
@@ -51,29 +51,4 @@
     @NotBlank(message = "鏍戣妭鐐瑰悕涓嶈兘涓虹┖", groups = { AddGroup.class, EditGroup.class })
     private String treeName;
 
-
-    /**
-     * 鍒嗛〉澶у皬
-     */
-    @ApiModelProperty("鍒嗛〉澶у皬")
-    private Integer pageSize;
-
-    /**
-     * 褰撳墠椤垫暟
-     */
-    @ApiModelProperty("褰撳墠椤垫暟")
-    private Integer pageNum;
-
-    /**
-     * 鎺掑簭鍒�
-     */
-    @ApiModelProperty("鎺掑簭鍒�")
-    private String orderByColumn;
-
-    /**
-     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
-     */
-    @ApiModelProperty(value = "鎺掑簭鐨勬柟鍚�", example = "asc,desc")
-    private String isAsc;
-
 }
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
index dccea61..7a3cb62 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoMapper.java
@@ -1,11 +1,19 @@
 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.mybatisplus.core.BaseMapperPlus;
 import com.ruoyi.demo.domain.TestDemo;
 import com.ruoyi.demo.domain.vo.TestDemoVo;
 import org.apache.ibatis.annotations.Param;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * 娴嬭瘯鍗曡〃Mapper鎺ュ彛
@@ -15,6 +23,37 @@
  */
 public interface TestDemoMapper extends BaseMapperPlus<TestDemo> {
 
+    @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.COLLECTION) Collection<? extends Serializable> 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
index 05b0153..0a7936c 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestTreeMapper.java
@@ -1,5 +1,7 @@
 package com.ruoyi.demo.mapper;
 
+import com.ruoyi.common.annotation.DataColumn;
+import com.ruoyi.common.annotation.DataPermission;
 import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
 import com.ruoyi.demo.domain.TestTree;
 
@@ -9,6 +11,10 @@
  * @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<TestTree> {
 
 }
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
index eb4f21b..12834d3 100644
--- a/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
+++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/service/ITestDemoService.java
@@ -1,5 +1,6 @@
 package com.ruoyi.demo.service;
 
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.demo.domain.TestDemo;
 import com.ruoyi.demo.domain.vo.TestDemoVo;
 import com.ruoyi.demo.domain.bo.TestDemoBo;
@@ -26,12 +27,12 @@
 	/**
 	 * 鏌ヨ鍒楄〃
 	 */
-    TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo);
+    TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery);
 
 	/**
 	 * 鑷畾涔夊垎椤垫煡璇�
 	 */
-	TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo);
+	TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery);
 
     /**
 	 * 鏌ヨ鍒楄〃
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
index 4280d50..a647d24 100644
--- 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
@@ -1,15 +1,13 @@
 package com.ruoyi.demo.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
-import com.ruoyi.common.utils.StringUtils;
 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.annotation.DataScope;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
-import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.PageUtils;
+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;
@@ -35,24 +33,23 @@
 		return getVoById(id);
 	}
 
-	@DataScope(isUser = true)
 	@Override
-	public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo) {
-		PagePlus<TestDemo, TestDemoVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
-		return PageUtils.buildDataInfo(result);
+	public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
+        Page<TestDemoVo> result = pageVo(pageQuery.build(), lqw);
+		return TableDataInfo.build(result);
 	}
 
 	/**
 	 * 鑷畾涔夊垎椤垫煡璇�
 	 */
-	@DataScope(isUser = true)
 	@Override
-	public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo) {
-		Page<TestDemoVo> result = baseMapper.customPageList(PageUtils.buildPage(), buildQueryWrapper(bo));
-		return PageUtils.buildDataInfo(result);
+	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);
 	}
 
-	@DataScope(isUser = true)
 	@Override
 	public List<TestDemoVo> queryList(TestDemoBo bo) {
 		return listVo(buildQueryWrapper(bo));
@@ -60,14 +57,11 @@
 
 	private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) {
 		Map<String, Object> params = bo.getParams();
-		Object dataScope = params.get("dataScope");
 		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"));
-		lqw.apply(dataScope != null && StringUtils.isNotBlank(dataScope.toString()),
-			dataScope != null ? dataScope.toString() : null);
 		return lqw;
 	}
 
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
index e793a86..c4097e6 100644
--- 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
@@ -3,7 +3,6 @@
 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.annotation.DataScope;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.demo.domain.TestTree;
@@ -23,7 +22,7 @@
  * @author Lion Li
  * @date 2021-07-26
  */
-//@DataSource(DataSourceType.SLAVE) // 鍒囨崲浠庡簱鏌ヨ
+// @DS("slave") // 鍒囨崲浠庡簱鏌ヨ
 @Service
 public class TestTreeServiceImpl extends ServicePlusImpl<TestTreeMapper, TestTree, TestTreeVo> implements ITestTreeService {
 
@@ -32,22 +31,19 @@
 		return getVoById(id);
 	}
 
-//	@DataSource(DataSourceType.SLAVE) // 鍒囨崲浠庡簱鏌ヨ
-	@DataScope(isUser = true)
+//	@DS("slave") // 鍒囨崲浠庡簱鏌ヨ
 	@Override
 	public List<TestTreeVo> queryList(TestTreeBo bo) {
-		return listVo(buildQueryWrapper(bo));
+        LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo);
+        return listVo(lqw);
 	}
 
 	private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) {
 		Map<String, Object> params = bo.getParams();
-		Object dataScope = params.get("dataScope");
 		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"));
-		lqw.apply(dataScope != null && StringUtils.isNotBlank(dataScope.toString()),
-			dataScope != null ? dataScope.toString() : null);
 		return lqw;
 	}
 
diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java
index 7335e2f..04a0fde 100644
--- a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java
+++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java
@@ -2,7 +2,6 @@
 
 import de.codecentric.boot.admin.server.config.AdminServerProperties;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@@ -15,7 +14,6 @@
  */
 @Configuration
 @EnableWebSecurity
-@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
 	private final String adminContextPath;
@@ -34,8 +32,8 @@
 			//鎺堜簣瀵规墍鏈夐潤鎬佽祫浜у拰鐧诲綍椤甸潰鐨勫叕鍏辫闂潈闄愩��
 			.antMatchers(adminContextPath + "/assets/**").permitAll()
 			.antMatchers(adminContextPath + "/login").permitAll()
-            .antMatchers("/actuator").anonymous()
-            .antMatchers("/actuator/**").anonymous()
+            .antMatchers("/actuator").permitAll()
+            .antMatchers("/actuator/**").permitAll()
 			//蹇呴』瀵规瘡涓叾浠栬姹傝繘琛岃韩浠介獙璇�
 			.anyRequest().authenticated().and()
 			//閰嶇疆鐧诲綍鍜屾敞閿�
diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
index 29786ee..835d7de 100644
--- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
+++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml
@@ -102,6 +102,7 @@
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
 				<configuration>
 					<nonFilteredFileExtensions>
 						<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java
index 57c1c08..e55b890 100644
--- a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java
+++ b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java
@@ -3,8 +3,8 @@
 import com.xxl.job.admin.core.util.FtlUtil;
 import com.xxl.job.admin.core.util.I18nUtil;
 import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.AsyncHandlerInterceptor;
 import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
@@ -17,7 +17,7 @@
  * @author xuxueli 2015-12-12 18:09:04
  */
 @Component
-public class CookieInterceptor extends HandlerInterceptorAdapter {
+public class CookieInterceptor implements AsyncHandlerInterceptor {
 
 	@Override
 	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@@ -36,8 +36,8 @@
 		if (modelAndView != null) {
 			modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName()));
 		}
-		
-		super.postHandle(request, response, handler, modelAndView);
+
+		AsyncHandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
 	}
-	
+
 }
diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java
index 5202c29..19eac73 100644
--- a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java
+++ b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java
@@ -6,7 +6,7 @@
 import com.xxl.job.admin.service.LoginService;
 import org.springframework.stereotype.Component;
 import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+import org.springframework.web.servlet.AsyncHandlerInterceptor;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
@@ -18,16 +18,16 @@
  * @author xuxueli 2015-12-12 18:09:04
  */
 @Component
-public class PermissionInterceptor extends HandlerInterceptorAdapter {
+public class PermissionInterceptor implements AsyncHandlerInterceptor {
 
 	@Resource
 	private LoginService loginService;
 
 	@Override
 	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-		
+
 		if (!(handler instanceof HandlerMethod)) {
-			return super.preHandle(request, response, handler);
+			return AsyncHandlerInterceptor.super.preHandle(request, response, handler);
 		}
 
 		// if need login
@@ -53,7 +53,7 @@
 			request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser);
 		}
 
-		return super.preHandle(request, response, handler);
+		return AsyncHandlerInterceptor.super.preHandle(request, response, handler);
 	}
-	
+
 }
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
index d5466af..713c5ab 100644
--- a/ruoyi-framework/pom.xml
+++ b/ruoyi-framework/pom.xml
@@ -46,23 +46,33 @@
             <artifactId>druid-spring-boot-starter</artifactId>
         </dependency>
 
-        <!-- dynamic-datasource 澶氭暟鎹簮-->
-        <dependency>
-            <groupId>com.baomidou</groupId>
-            <artifactId>dynamic-datasource-spring-boot-starter</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.ruoyi</groupId>
             <artifactId>ruoyi-common</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>tlog-web-spring-boot-starter</artifactId>
+        </dependency>
+
     </dependencies>
 
 </project>
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 e2120bf..0000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/Interceptor/PlusWebInvokeTimeInterceptor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.ruoyi.framework.Interceptor;
-
-import cn.hutool.core.map.MapUtil;
-import com.alibaba.ttl.TransmittableThreadLocal;
-import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.yomahub.tlog.context.TLogContext;
-import com.yomahub.tlog.web.interceptor.AbsTLogWebHandlerMethodInterceptor;
-import com.yomahub.tlog.web.wrapper.RequestWrapper;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.time.StopWatch;
-import org.springframework.http.MediaType;
-import org.springframework.web.servlet.ModelAndView;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Map;
-
-/**
- * 閲嶅啓Tlog web鐨勮皟鐢ㄦ椂闂寸粺璁℃嫤鎴櫒
- *
- * @author Lion Li
- * @since 3.3.0
- */
-@Slf4j
-public class PlusWebInvokeTimeInterceptor extends AbsTLogWebHandlerMethodInterceptor {
-
-    private final TransmittableThreadLocal<StopWatch> invokeTimeTL = new TransmittableThreadLocal<>();
-
-    @Override
-    public boolean preHandleByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-        if (TLogContext.enableInvokeTimePrint()) {
-            String url = request.getMethod() + " " + request.getRequestURI();
-
-            // 鎵撳嵃璇锋眰鍙傛暟
-            if (isJsonRequest(request)) {
-                    String jsonParam = new RequestWrapper(request).getBodyString();
-                    log.info("[PLUS]寮�濮嬭姹� => URL[{}],鍙傛暟绫诲瀷[json],鍙傛暟:[{}]", url, jsonParam);
-            } else {
-                Map<String, String[]> parameterMap = request.getParameterMap();
-                if (MapUtil.isNotEmpty(parameterMap)) {
-                    String parameters = JsonUtils.toJsonString(parameterMap);
-                    log.info("[PLUS]寮�濮嬭姹� => URL[{}],鍙傛暟绫诲瀷[param],鍙傛暟:[{}]", url, parameters);
-                } else {
-                    log.info("[PLUS]寮�濮嬭姹� => URL[{}],鏃犲弬鏁�", url);
-                }
-            }
-
-            StopWatch stopWatch = new StopWatch();
-            invokeTimeTL.set(stopWatch);
-            stopWatch.start();
-        }
-        return true;
-    }
-
-    @Override
-    public void postHandleByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
-
-    }
-
-    @Override
-    public void afterCompletionByHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
-        if (TLogContext.enableInvokeTimePrint()) {
-            StopWatch stopWatch = invokeTimeTL.get();
-            stopWatch.stop();
-            log.info("[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/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
index 393b2e6..2e02c74 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -12,15 +12,15 @@
 import org.aspectj.lang.annotation.Before;
 import org.springframework.stereotype.Component;
 
-import java.util.Map;
-
 /**
  * 鏁版嵁杩囨护澶勭悊
  *
  * @author Lion Li
+ * @deprecated 3.6.0 绉婚櫎 {@link com.ruoyi.framework.handler.PlusDataPermissionHandler}
  */
 @Aspect
 @Component
+@Deprecated
 public class DataScopeAspect {
 
 	/**
@@ -131,9 +131,6 @@
 			if (params instanceof BaseEntity) {
 				BaseEntity baseEntity = (BaseEntity) params;
 				baseEntity.getParams().put(DATA_SCOPE, sql);
-			} else {
-				Map<String, Object> invoke = ReflectUtils.invokeGetter(params, "params");
-				invoke.put(DATA_SCOPE, sql);
 			}
 		}
 	}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
index 45ffe3b..0b1c898 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
@@ -18,10 +18,12 @@
  * 澶氭暟鎹簮澶勭悊
  *
  * @author Lion Li
+ * @deprecated 3.6.0 绉婚櫎 浣跨敤鍘熺敓鏂规硶澶勭悊 鍔熻兘鏇村叏
  */
 @Aspect
 @Order(-500)
 @Component
+@Deprecated
 public class DataSourceAspect {
 
 	@Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
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
index df4d9c8..ce3de2b 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
@@ -54,7 +54,7 @@
             stringBuffer.append(ServletUtils.getClientIP()).append("-");
         } else if (rateLimiter.limitType() == LimitType.CLUSTER){
             // 鑾峰彇瀹㈡埛绔疄渚媔d
-            stringBuffer.append(RedisUtils.getClientId()).append("-");
+            stringBuffer.append(RedisUtils.getClient().getId()).append("-");
         }
         MethodSignature signature = (MethodSignature) point.getSignature();
         Method method = signature.getMethod();
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
index db81b74..5daaa9a 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
@@ -1,6 +1,9 @@
 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.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
 import com.baomidou.mybatisplus.core.injector.ISqlInjector;
@@ -10,6 +13,7 @@
 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
 import com.ruoyi.common.core.mybatisplus.methods.InsertAll;
 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;
@@ -30,12 +34,21 @@
 	@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();
+    }
 
 	/**
 	 * 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷
@@ -79,24 +92,33 @@
 		};
 	}
 
+    /**
+     * 浣跨敤缃戝崱淇℃伅缁戝畾闆姳鐢熸垚鍣�
+     * 闃叉闆嗙兢闆姳ID閲嶅
+     */
+    @Bean
+    public IdentifierGenerator idGenerator() {
+        return new DefaultIdentifierGenerator(NetUtil.getLocalhost());
+    }
+
 	/**
 	 * PaginationInnerInterceptor 鍒嗛〉鎻掍欢锛岃嚜鍔ㄨ瘑鍒暟鎹簱绫诲瀷
-	 * https://baomidou.com/guide/interceptor-pagination.html
+	 * https://baomidou.com/pages/97710a/
 	 * OptimisticLockerInnerInterceptor 涔愯閿佹彃浠�
-	 * https://baomidou.com/guide/interceptor-optimistic-locker.html
+	 * https://baomidou.com/pages/0d93c0/
 	 * MetaObjectHandler 鍏冨璞″瓧娈靛~鍏呮帶鍒跺櫒
-	 * https://baomidou.com/guide/auto-fill-metainfo.html
+	 * https://baomidou.com/pages/4c6bcf/
 	 * ISqlInjector sql娉ㄥ叆鍣�
-	 * https://baomidou.com/guide/sql-injector.html
+	 * https://baomidou.com/pages/42ea4a/
 	 * BlockAttackInnerInterceptor 濡傛灉鏄鍏ㄨ〃鐨勫垹闄ゆ垨鏇存柊鎿嶄綔锛屽氨浼氱粓姝㈣鎿嶄綔
-	 * https://baomidou.com/guide/interceptor-block-attack.html
+	 * https://baomidou.com/pages/f9a237/
 	 * IllegalSQLInnerInterceptor sql鎬ц兘瑙勮寖鎻掍欢(鍨冨溇SQL鎷︽埅)
 	 * IdentifierGenerator 鑷畾涔変富閿瓥鐣�
-	 * https://baomidou.com/guide/id-generator.html
+	 * https://baomidou.com/pages/568eb2/
 	 * TenantLineInnerInterceptor 澶氱鎴锋彃浠�
-	 * https://baomidou.com/guide/interceptor-tenant-line.html
+	 * https://baomidou.com/pages/aef2f2/
 	 * DynamicTableNameInnerInterceptor 鍔ㄦ�佽〃鍚嶆彃浠�
-	 * https://baomidou.com/guide/interceptor-dynamic-table-name.html
+	 * 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
index d7ae1cd..6fa54e2 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
@@ -23,6 +23,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * redis閰嶇疆
@@ -34,158 +35,164 @@
 @EnableCaching
 public class RedisConfig extends CachingConfigurerSupport {
 
-	private static final String REDIS_PROTOCOL_PREFIX = "redis://";
-	private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
+    private static final String REDIS_PROTOCOL_PREFIX = "redis://";
+    private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
 
-	@Autowired
-	private RedisProperties redisProperties;
+    @Autowired
+    private RedisProperties redisProperties;
 
-	@Autowired
-	private RedissonProperties redissonProperties;
+    @Autowired
+    private RedissonProperties redissonProperties;
 
-	@Bean(destroyMethod = "shutdown")
-	@ConditionalOnMissingBean(RedissonClient.class)
-	public RedissonClient redisson() throws IOException {
-		String prefix = REDIS_PROTOCOL_PREFIX;
-		if (redisProperties.isSsl()) {
-			prefix = REDISS_PROTOCOL_PREFIX;
-		}
-		Config config = new Config();
-		config.setThreads(redissonProperties.getThreads())
-			.setNettyThreads(redissonProperties.getNettyThreads())
-			.setCodec(JsonJacksonCodec.INSTANCE)
-			.setTransportMode(redissonProperties.getTransportMode());
+    @Bean(destroyMethod = "shutdown")
+    @ConditionalOnMissingBean(RedissonClient.class)
+    public RedissonClient redisson() throws IOException {
+        String prefix = REDIS_PROTOCOL_PREFIX;
+        if (redisProperties.isSsl()) {
+            prefix = REDISS_PROTOCOL_PREFIX;
+        }
+        Config config = new Config();
+        config.setThreads(redissonProperties.getThreads())
+            .setNettyThreads(redissonProperties.getNettyThreads())
+            .setCodec(JsonJacksonCodec.INSTANCE)
+            .setTransportMode(redissonProperties.getTransportMode());
 
-		RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
-		if (ObjectUtil.isNotNull(singleServerConfig)) {
-			// 浣跨敤鍗曟満妯″紡
-			config.useSingleServer()
-					.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
-					.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
-					.setDatabase(redisProperties.getDatabase())
-					.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
-					.setTimeout(singleServerConfig.getTimeout())
-					.setRetryAttempts(singleServerConfig.getRetryAttempts())
-					.setRetryInterval(singleServerConfig.getRetryInterval())
-					.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
-					.setClientName(singleServerConfig.getClientName())
-					.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
-					.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
-					.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
-					.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
-					.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
-					.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
-		}
-		// 闆嗙兢閰嶇疆鏂瑰紡 鍙傝�冧笅鏂规敞閲�
-		RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
-		if (ObjectUtil.isNotNull(clusterServersConfig)) {
-			// 浣跨敤闆嗙兢妯″紡
-			config.useClusterServers()
-					.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
-					.setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
-					.setTimeout(clusterServersConfig.getTimeout())
-					.setRetryAttempts(clusterServersConfig.getRetryAttempts())
-					.setRetryInterval(clusterServersConfig.getRetryInterval())
-					.setSubscriptionsPerConnection(clusterServersConfig.getSubscriptionsPerConnection())
-					.setClientName(clusterServersConfig.getClientName())
-					.setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
-					.setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
-					.setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize())
-					.setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
-					.setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
-					.setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
-					.setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
-					.setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
-					.setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval())
-					.setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval())
-					.setScanInterval(clusterServersConfig.getScanInterval())
-					.setReadMode(clusterServersConfig.getReadMode())
-					.setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
-					.setNodeAddresses(redisProperties.getCluster().getNodes());
-		}
-		RedissonClient redissonClient = Redisson.create(config);
-		log.info("鍒濆鍖� redis 閰嶇疆");
-		return redissonClient;
-	}
+        RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
+        if (ObjectUtil.isNotNull(singleServerConfig)) {
+            // 浣跨敤鍗曟満妯″紡
+            config.useSingleServer()
+                .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
+                .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+                .setDatabase(redisProperties.getDatabase())
+                .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+                .setTimeout(singleServerConfig.getTimeout())
+                .setRetryAttempts(singleServerConfig.getRetryAttempts())
+                .setRetryInterval(singleServerConfig.getRetryInterval())
+                .setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
+                .setClientName(singleServerConfig.getClientName())
+                .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
+                .setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
+                .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
+                .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
+                .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
+                .setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
+        }
+        // 闆嗙兢閰嶇疆鏂瑰紡 鍙傝�冧笅鏂规敞閲�
+        RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig();
+        if (ObjectUtil.isNotNull(clusterServersConfig)) {
+            // 浣跨敤闆嗙兢妯″紡
+            String finalPrefix = prefix;
+            List<String> nodes = redisProperties.getCluster().getNodes()
+                .stream()
+                .map(node -> finalPrefix + node)
+                .collect(Collectors.toList());
 
-	/**
-	 * 鏁村悎spring-cache
-	 */
-	@Bean
-	public CacheManager cacheManager(RedissonClient redissonClient) {
-		List<RedissonProperties.CacheGroup> cacheGroup = redissonProperties.getCacheGroup();
-		Map<String, CacheConfig> config = new HashMap<>();
-		for (RedissonProperties.CacheGroup group : cacheGroup) {
-			CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime());
-			cacheConfig.setMaxSize(group.getMaxSize());
-			config.put(group.getGroupId(), cacheConfig);
-		}
-		return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
-	}
+            config.useClusterServers()
+                .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+                .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+                .setTimeout(clusterServersConfig.getTimeout())
+                .setRetryAttempts(clusterServersConfig.getRetryAttempts())
+                .setRetryInterval(clusterServersConfig.getRetryInterval())
+                .setSubscriptionsPerConnection(clusterServersConfig.getSubscriptionsPerConnection())
+                .setClientName(clusterServersConfig.getClientName())
+                .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout())
+                .setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval())
+                .setSubscriptionConnectionMinimumIdleSize(clusterServersConfig.getSubscriptionConnectionMinimumIdleSize())
+                .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize())
+                .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize())
+                .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize())
+                .setSlaveConnectionMinimumIdleSize(clusterServersConfig.getSlaveConnectionMinimumIdleSize())
+                .setSlaveConnectionPoolSize(clusterServersConfig.getSlaveConnectionPoolSize())
+                .setDnsMonitoringInterval(clusterServersConfig.getDnsMonitoringInterval())
+                .setFailedSlaveReconnectionInterval(clusterServersConfig.getFailedSlaveReconnectionInterval())
+                .setScanInterval(clusterServersConfig.getScanInterval())
+                .setReadMode(clusterServersConfig.getReadMode())
+                .setSubscriptionMode(clusterServersConfig.getSubscriptionMode())
+                .setNodeAddresses(nodes);
+        }
+        RedissonClient redissonClient = Redisson.create(config);
+        log.info("鍒濆鍖� redis 閰嶇疆");
+        return redissonClient;
+    }
 
-	/**
-	 * 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
-	 *   # 浼犺緭妯″紡
-	 *   transportMode: "NIO"
-	 *   # 闆嗙兢閰嶇疆
-	 *   clusterServersConfig:
-	 *     # 瀹㈡埛绔悕绉�
-	 *     clientName: ${ruoyi.name}
-	 *     # master鏈�灏忕┖闂茶繛鎺ユ暟
-	 *     masterConnectionMinimumIdleSize: 32
-	 *     # master杩炴帴姹犲ぇ灏�
-	 *     masterConnectionPoolSize: 64
-	 *     # slave鏈�灏忕┖闂茶繛鎺ユ暟
-	 *     slaveConnectionMinimumIdleSize: 32
-	 *     # slave杩炴帴姹犲ぇ灏�
-	 *     slaveConnectionPoolSize: 64
-	 *     # 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
-	 *     idleConnectionTimeout: 10000
-	 *     # ping杩炴帴闂撮殧
-	 *     pingConnectionInterval: 1000
-	 *     # 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
-	 *     timeout: 3000
-	 *     # 濡傛灉灏濊瘯鍦ㄦ闄愬埗涔嬪唴鍙戦�佹垚鍔燂紝鍒欏紑濮嬪惎鐢� timeout 璁℃椂銆�
-	 *     retryAttempts: 3
-	 *     # 鍛戒护閲嶈瘯鍙戦�佹椂闂撮棿闅旓紝鍗曚綅锛氭绉�
-	 *     retryInterval: 1500
-	 *     # 浠庡彲鐢ㄦ湇鍔″櫒鐨勫唴閮ㄥ垪琛ㄤ腑鎺掗櫎 Redis Slave 閲嶆柊杩炴帴灏濊瘯鐨勯棿闅斻��
-	 *     failedSlaveReconnectionInterval: 3000
-	 *     # 鍙戝竷鍜岃闃呰繛鎺ユ睜鏈�灏忕┖闂茶繛鎺ユ暟
-	 *     subscriptionConnectionMinimumIdleSize: 1
-	 *     # 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
-	 *     subscriptionConnectionPoolSize: 50
-	 *     # 鍗曚釜杩炴帴鏈�澶ц闃呮暟閲�
-	 *     subscriptionsPerConnection: 5
-	 *     # 鎵弿闂撮殧
-	 *     scanInterval: 1000
-	 *     # DNS鐩戞祴鏃堕棿闂撮殧锛屽崟浣嶏細姣
-	 *     dnsMonitoringInterval: 5000
-	 *     # 璇诲彇妯″紡
-	 *     readMode: "SLAVE"
-	 *     # 璁㈤槄妯″紡
-	 *     subscriptionMode: "MASTER"
-	 */
+    /**
+     * 鏁村悎spring-cache
+     */
+    @Bean
+    public CacheManager cacheManager(RedissonClient redissonClient) {
+        List<RedissonProperties.CacheGroup> cacheGroup = redissonProperties.getCacheGroup();
+        Map<String, CacheConfig> config = new HashMap<>();
+        for (RedissonProperties.CacheGroup group : cacheGroup) {
+            CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime());
+            cacheConfig.setMaxSize(group.getMaxSize());
+            config.put(group.getGroupId(), cacheConfig);
+        }
+        return new RedissonSpringCacheManager(redissonClient, config, JsonJacksonCodec.INSTANCE);
+    }
+
+    /**
+     * 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
+     *   # 浼犺緭妯″紡
+     *   transportMode: "NIO"
+     *   # 闆嗙兢閰嶇疆
+     *   clusterServersConfig:
+     *     # 瀹㈡埛绔悕绉�
+     *     clientName: ${ruoyi.name}
+     *     # master鏈�灏忕┖闂茶繛鎺ユ暟
+     *     masterConnectionMinimumIdleSize: 32
+     *     # master杩炴帴姹犲ぇ灏�
+     *     masterConnectionPoolSize: 64
+     *     # slave鏈�灏忕┖闂茶繛鎺ユ暟
+     *     slaveConnectionMinimumIdleSize: 32
+     *     # slave杩炴帴姹犲ぇ灏�
+     *     slaveConnectionPoolSize: 64
+     *     # 杩炴帴绌洪棽瓒呮椂锛屽崟浣嶏細姣
+     *     idleConnectionTimeout: 10000
+     *     # ping杩炴帴闂撮殧
+     *     pingConnectionInterval: 1000
+     *     # 鍛戒护绛夊緟瓒呮椂锛屽崟浣嶏細姣
+     *     timeout: 3000
+     *     # 濡傛灉灏濊瘯鍦ㄦ闄愬埗涔嬪唴鍙戦�佹垚鍔燂紝鍒欏紑濮嬪惎鐢� timeout 璁℃椂銆�
+     *     retryAttempts: 3
+     *     # 鍛戒护閲嶈瘯鍙戦�佹椂闂撮棿闅旓紝鍗曚綅锛氭绉�
+     *     retryInterval: 1500
+     *     # 浠庡彲鐢ㄦ湇鍔″櫒鐨勫唴閮ㄥ垪琛ㄤ腑鎺掗櫎 Redis Slave 閲嶆柊杩炴帴灏濊瘯鐨勯棿闅斻��
+     *     failedSlaveReconnectionInterval: 3000
+     *     # 鍙戝竷鍜岃闃呰繛鎺ユ睜鏈�灏忕┖闂茶繛鎺ユ暟
+     *     subscriptionConnectionMinimumIdleSize: 1
+     *     # 鍙戝竷鍜岃闃呰繛鎺ユ睜澶у皬
+     *     subscriptionConnectionPoolSize: 50
+     *     # 鍗曚釜杩炴帴鏈�澶ц闃呮暟閲�
+     *     subscriptionsPerConnection: 5
+     *     # 鎵弿闂撮殧
+     *     scanInterval: 1000
+     *     # DNS鐩戞祴鏃堕棿闂撮殧锛屽崟浣嶏細姣
+     *     dnsMonitoringInterval: 5000
+     *     # 璇诲彇妯″紡
+     *     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
index b6e33ac..f43ecab 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -1,6 +1,6 @@
 package com.ruoyi.framework.config;
 
-import com.ruoyi.framework.Interceptor.PlusWebInvokeTimeInterceptor;
+import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor;
 import com.yomahub.tlog.web.interceptor.TLogWebInterceptor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
index c1665d9..5ae55ad 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java
@@ -1,13 +1,8 @@
 package com.ruoyi.framework.config;
 
-import com.yomahub.tlog.core.aop.AspectLogAop;
-import com.yomahub.tlog.spring.TLogPropertyInit;
-import com.yomahub.tlog.spring.TLogSpringAware;
-import com.yomahub.tlog.springboot.property.TLogProperty;
-import org.springframework.context.annotation.Bean;
+import com.yomahub.tlog.springboot.TLogWebAutoConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.core.annotation.Order;
 
 /**
  * 鏁村悎 TLog 妗嗘灦閰嶇疆
@@ -15,29 +10,9 @@
  * @author Lion Li
  * @since 3.3.0
  */
-@Order(-999)
 @Configuration
-@Import(TLogProperty.class)
+// 鎺掗櫎 web 鑷姩閰嶇疆 鑷畾涔夊疄鐜�
+@EnableAutoConfiguration(exclude = TLogWebAutoConfiguration.class)
 public class TLogConfig {
-
-    @Bean
-    public TLogPropertyInit tLogPropertyInit(TLogProperty tLogProperty) {
-        TLogPropertyInit tLogPropertyInit = new TLogPropertyInit();
-        tLogPropertyInit.setPattern(tLogProperty.getPattern());
-        tLogPropertyInit.setEnableInvokeTimePrint(tLogProperty.enableInvokeTimePrint());
-        tLogPropertyInit.setIdGenerator(tLogProperty.getIdGenerator());
-        tLogPropertyInit.setMdcEnable(tLogProperty.getMdcEnable());
-        return tLogPropertyInit;
-    }
-
-    @Bean
-    public TLogSpringAware tLogSpringAware(){
-        return new TLogSpringAware();
-    }
-
-    @Bean
-    public AspectLogAop aspectLogAop() {
-        return new AspectLogAop();
-    }
 
 }
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
new file mode 100644
index 0000000..d5f4f58
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java
@@ -0,0 +1,192 @@
+package com.ruoyi.framework.handler;
+
+import cn.hutool.core.annotation.AnnotationUtil;
+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.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.service.UserService;
+import com.ruoyi.common.enums.DataScopeType;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.helper.DataPermissionHelper;
+import com.ruoyi.common.utils.SecurityUtils;
+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.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+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> inavlidCacheSet = 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)) {
+            inavlidCacheSet.add(mappedStatementId);
+            return where;
+        }
+        SysUser currentUser = DataPermissionHelper.getVariable("user");
+        if (ObjectUtil.isNull(currentUser)) {
+            currentUser = SpringUtils.getBean(UserService.class).selectUserById(SecurityUtils.getUserId());
+            DataPermissionHelper.setVariable("user", currentUser);
+        }
+        // 濡傛灉鏄秴绾х鐞嗗憳锛屽垯涓嶈繃婊ゆ暟鎹�
+        if (ObjectUtil.isNull(currentUser) || currentUser.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) {
+        StringBuilder sqlString = new StringBuilder();
+        // 鏇存柊鎴栧垹闄ら渶婊¤冻鎵�鏈夋潯浠�
+        String joinStr = isSelect ? " OR " : " AND ";
+        SysUser user = DataPermissionHelper.getVariable("user");
+        StandardEvaluationContext context = new StandardEvaluationContext();
+        context.setBeanResolver(beanResolver);
+        DataPermissionHelper.getContext().forEach(context::setVariable);
+        for (SysRole 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) {
+                // 涓嶅寘鍚� key 鍙橀噺 鍒欎笉澶勭悊
+                if (!StringUtils.contains(type.getSqlTemplate(), "#" + dataColumn.key())) {
+                    continue;
+                }
+                // 璁剧疆娉ㄨВ鍙橀噺 key 涓鸿〃杈惧紡鍙橀噺 value 涓哄彉閲忓��
+                context.setVariable(dataColumn.key(), dataColumn.value());
+
+                // 瑙f瀽sql妯℃澘骞跺~鍏�
+                String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class);
+                sqlString.append(joinStr).append(sql);
+                isSuccess = true;
+            }
+            // 鏈鐞嗘垚鍔熷垯濉厖鍏滃簳鏂规
+            if (!isSuccess) {
+                sqlString.append(joinStr).append(type.getElseSql());
+            }
+        }
+
+        if (StringUtils.isNotBlank(sqlString.toString())) {
+            return sqlString.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(method.getName());
+            if (ObjectUtil.isNotNull(dataPermission)) {
+                return dataPermission.value();
+            }
+            if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) {
+                dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class);
+                dataPermissionCacheMap.put(method.getName(), 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 inavlidCacheSet.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
new file mode 100644
index 0000000..508f421
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusDataPermissionInterceptor.java
@@ -0,0 +1,108 @@
+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
new file mode 100644
index 0000000..9ba4cff
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java
@@ -0,0 +1,92 @@
+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 javax.servlet.http.HttpServletRequest;
+import javax.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 TransmittableThreadLocal<StopWatch> invokeTimeTL = new TransmittableThreadLocal<>();
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        if (!"prod".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 (!"prod".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-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
index af85c84..f1ff61a 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
@@ -6,6 +6,7 @@
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.generator.domain.GenTable;
@@ -46,8 +47,8 @@
     @ApiOperation("鏌ヨ浠g爜鐢熸垚鍒楄〃")
     @SaCheckPermission("tool:gen:list")
     @GetMapping("/list")
-    public TableDataInfo<GenTable> genList(GenTable genTable) {
-        return genTableService.selectPageGenTableList(genTable);
+    public TableDataInfo<GenTable> genList(GenTable genTable, PageQuery pageQuery) {
+        return genTableService.selectPageGenTableList(genTable, pageQuery);
     }
 
     /**
@@ -73,8 +74,8 @@
     @ApiOperation("鏌ヨ鏁版嵁搴撳垪琛�")
     @SaCheckPermission("tool:gen:list")
     @GetMapping("/db/list")
-    public TableDataInfo<GenTable> dataList(GenTable genTable) {
-        return genTableService.selectPageDbTableList(genTable);
+    public TableDataInfo<GenTable> dataList(GenTable genTable, PageQuery pageQuery) {
+        return genTableService.selectPageDbTableList(genTable, pageQuery);
     }
 
     /**
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
index 1f7e20c..d81a45a 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
@@ -1,5 +1,6 @@
 package com.ruoyi.generator.mapper;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
 import com.ruoyi.generator.domain.GenTableColumn;
 
@@ -10,6 +11,7 @@
  *
  * @author Lion Li
  */
+@InterceptorIgnore(dataPermission = "true")
 public interface GenTableColumnMapper extends BaseMapperPlus<GenTableColumn> {
     /**
      * 鏍规嵁琛ㄥ悕绉版煡璇㈠垪淇℃伅
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
index c55a9a2..8ea66a2 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
@@ -1,5 +1,6 @@
 package com.ruoyi.generator.mapper;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
 import com.ruoyi.generator.domain.GenTable;
@@ -12,6 +13,7 @@
  *
  * @author Lion Li
  */
+@InterceptorIgnore(dataPermission = "true")
 public interface GenTableMapper extends BaseMapperPlus<GenTable> {
 
 
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
index 35b1c95..ea1dfc1 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
@@ -4,8 +4,10 @@
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.IoUtil;
 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.constant.GenConstants;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.exception.ServiceException;
@@ -63,13 +65,15 @@
     }
 
     @Override
-    public TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable) {
-        return PageUtils.buildDataInfo(baseMapper.selectPageGenTableList(PageUtils.buildPage(), genTable));
+    public TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery) {
+        Page<GenTable> page = baseMapper.selectPageGenTableList(pageQuery.build(), genTable);
+        return TableDataInfo.build(page);
     }
 
     @Override
-    public TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable) {
-        return PageUtils.buildDataInfo(baseMapper.selectPageDbTableList(PageUtils.buildPage(), genTable));
+    public TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery) {
+        Page<GenTable> page = baseMapper.selectPageDbTableList(pageQuery.build(), genTable);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -122,7 +126,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void updateGenTable(GenTable genTable) {
         String options = JsonUtils.toJsonString(genTable.getParams());
         genTable.setOptions(options);
@@ -141,7 +145,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void deleteGenTableByIds(Long[] tableIds) {
         List<Long> ids = Arrays.asList(tableIds);
         removeByIds(ids);
@@ -154,7 +158,7 @@
      * @param tableList 瀵煎叆琛ㄥ垪琛�
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void importGenTable(List<GenTable> tableList) {
         String operName = LoginUtils.getUsername();
         try {
@@ -268,7 +272,7 @@
      * @param tableName 琛ㄥ悕绉�
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void synchDb(String tableName) {
         GenTable table = baseMapper.selectGenTableByName(tableName);
         List<GenTableColumn> tableColumns = table.getColumns();
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
index 1bf0c27..2f7832e 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.generator.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.generator.domain.GenTable;
 
@@ -15,10 +16,10 @@
 public interface IGenTableService extends IService<GenTable> {
 
 
-    TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable);
+    TableDataInfo<GenTable> selectPageGenTableList(GenTable genTable, PageQuery pageQuery);
 
 
-    TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable);
+    TableDataInfo<GenTable> selectPageDbTableList(GenTable genTable, PageQuery pageQuery);
 
     /**
      * 鏌ヨ涓氬姟鍒楄〃
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
index d2e0e3a..13f7d89 100644
--- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
@@ -9,10 +9,7 @@
 import com.ruoyi.generator.domain.GenTableColumn;
 import org.apache.velocity.VelocityContext;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * 妯℃澘澶勭悊宸ュ叿绫�
@@ -244,7 +241,7 @@
      */
     public static String getDicts(GenTable genTable) {
         List<GenTableColumn> columns = genTable.getColumns();
-        List<String> dicts = new ArrayList<String>();
+        Set<String> dicts = new HashSet<String>();
         for (GenTableColumn column : columns) {
             if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
                     column.getHtmlType(),
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
index 768b9fd..1aa9ea5 100644
--- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
+++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
@@ -27,7 +27,7 @@
 		<result property="remark"         column="remark"            />
 		<collection  property="columns"  javaType="java.util.List"  resultMap="GenTableColumnResult" />
 	</resultMap>
-	
+
 	<resultMap type="GenTableColumn" id="GenTableColumnResult">
         <id     property="columnId"       column="column_id"      />
         <result property="tableId"        column="table_id"       />
@@ -52,7 +52,7 @@
         <result property="updateBy"       column="update_by"      />
         <result property="updateTime"     column="update_time"    />
     </resultMap>
-	
+
 	<sql id="selectGenTableVo">
         select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
     </sql>
@@ -78,7 +78,7 @@
 	<select id="selectPageDbTableList" parameterType="GenTable" resultMap="GenTableResult">
 		select table_name, table_comment, create_time, update_time from information_schema.tables
 		where table_schema = (select database())
-		AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
+		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}, '%'))
@@ -117,7 +117,7 @@
 	<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
 		select table_name, table_comment, create_time, update_time from information_schema.tables
 		where table_schema = (select database())
-		AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
+		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="tableName != null and tableName != ''">
 			AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
@@ -133,22 +133,22 @@
 		</if>
         order by create_time desc
 	</select>
-	
+
 	<select id="selectDbTableListByNames" resultMap="GenTableResult">
 		select table_name, table_comment, create_time, update_time from information_schema.tables
-		where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
+		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> 
+        </foreach>
 	</select>
-	
+
 	<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
 		select table_name, table_comment, create_time, update_time from information_schema.tables
 		where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
 		and table_name = #{tableName}
 	</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
@@ -156,7 +156,7 @@
 			 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
@@ -164,7 +164,7 @@
 			 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
@@ -173,4 +173,4 @@
 		order by c.sort
 	</select>
 
-</mapper>
\ No newline at end of file
+</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
index 8831d0c..94d6050 100644
--- a/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
+++ b/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
@@ -63,28 +63,4 @@
 #end
 #end
 
-    /**
-     * 鍒嗛〉澶у皬
-     */
-    @ApiModelProperty("鍒嗛〉澶у皬")
-    private Integer pageSize;
-
-    /**
-     * 褰撳墠椤垫暟
-     */
-    @ApiModelProperty("褰撳墠椤垫暟")
-    private Integer pageNum;
-
-    /**
-     * 鎺掑簭鍒�
-     */
-    @ApiModelProperty("鎺掑簭鍒�")
-    private String orderByColumn;
-
-    /**
-     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
-     */
-    @ApiModelProperty(value = "鎺掑簭鐨勬柟鍚�", example = "asc,desc")
-    private String isAsc;
-
 }
diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
index d2e76ba..cd618fb 100644
--- a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
+++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
@@ -14,6 +14,7 @@
 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.AjaxResult;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
@@ -53,8 +54,8 @@
     @SaCheckPermission("${permissionPrefix}:list")
     @GetMapping("/list")
 #if($table.crud || $table.sub)
-    public TableDataInfo<${ClassName}Vo> list(@Validated(QueryGroup.class) ${ClassName}Bo bo) {
-        return i${ClassName}Service.queryPageList(bo);
+    public TableDataInfo<${ClassName}Vo> list(@Validated(QueryGroup.class) ${ClassName}Bo bo, PageQuery pageQuery) {
+        return i${ClassName}Service.queryPageList(bo, pageQuery);
     }
 #elseif($table.tree)
     public AjaxResult<List<${ClassName}Vo>> list(@Validated(QueryGroup.class) ${ClassName}Bo bo) {
diff --git a/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
index 0041c39..f93053c 100644
--- a/ruoyi-generator/src/main/resources/vm/java/service.java.vm
+++ b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
@@ -6,6 +6,7 @@
 import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
 #if($table.crud || $table.sub)
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.domain.PageQuery;
 #end
 
 import java.util.Collection;
@@ -28,7 +29,7 @@
 	/**
 	 * 鏌ヨ鍒楄〃
 	 */
-    TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo);
+    TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery);
 #end
 
 	/**
diff --git a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
index b9a45c6..bf20151 100644
--- a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
+++ b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
@@ -3,12 +3,12 @@
 import cn.hutool.core.bean.BeanUtil;
 import com.ruoyi.common.utils.StringUtils;
 #if($table.crud || $table.sub)
-import com.ruoyi.common.utils.PageUtils;
-import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.domain.PageQuery;
 #end
 import org.springframework.stereotype.Service;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import ${packageName}.domain.bo.${ClassName}Bo;
@@ -37,15 +37,17 @@
 
 #if($table.crud || $table.sub)
     @Override
-    public TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo) {
-        PagePlus<${ClassName}, ${ClassName}Vo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
-        return PageUtils.buildDataInfo(result);
+    public TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
+        Page<${ClassName}Vo> result = pageVo(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
     }
 #end
 
     @Override
     public List<${ClassName}Vo> queryList(${ClassName}Bo bo) {
-        return listVo(buildQueryWrapper(bo));
+        LambdaQueryWrapper<${ClassName}> lqw = buildQueryWrapper(bo);
+        return listVo(lqw);
     }
 
     private LambdaQueryWrapper<${ClassName}> buildQueryWrapper(${ClassName}Bo bo) {
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
new file mode 100644
index 0000000..55ddca5
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
@@ -0,0 +1,476 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input" || $column.htmlType == "textarea")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="璇疯緭鍏�${comment}"
+          clearable
+          size="small"
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable size="small">
+          <el-option
+            v-for="dict in ${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable size="small">
+          <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable size="small"
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="YYYY-MM-DD"
+          placeholder="閫夋嫨${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          size="small"
+          style="width: 240px"
+          value-format="YYYY-MM-DD"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <el-form-item>
+	    <el-button type="primary" icon="Search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="Refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >鏂板</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-loading="loading"
+      :data="${businessName}List"
+      row-key="${treeCode}"
+      default-expand-all
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+#elseif($column.list && $column.dictType && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template #default="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $javaField)
+#if(${foreach.index} == 1)
+      <el-table-column label="${comment}" prop="${javaField}" />
+#else
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+#end
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="Edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="Plus"
+            @click="handleAdd(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:add']"
+          >鏂板</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="Delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+        <el-form-item label="${comment}" prop="${treeParentCode}">
+          <tree-select
+            v-model:value="form.${treeParentCode}"
+            :options="${businessName}Options"
+            :objMap="{ value: '${treeCode}', label: '${treeName}', children: 'children' }"
+            placeholder="璇烽�夋嫨${comment}"
+          />
+        </el-form-item>
+#elseif($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}">
+          <imageUpload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}">
+          <fileUpload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
+
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
+
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable size="small"
+            v-model="form.${field}"
+            type="datetime"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            placeholder="閫夋嫨${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+          <el-button @click="cancel">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="${BusinessName}">
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+const { proxy } = getCurrentInstance();
+#if(${dicts} != '')
+#set($dictsNoSymbol=$dicts.replace("'", ""))
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
+#end
+
+const ${businessName}List = ref([]);
+const ${businessName}Options = ref([]);
+const open = ref(false);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const title = ref("");
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+const daterange${AttrName} = ref([]);
+#end
+#end
+
+const data = reactive({
+  form: {},
+  queryParams: {
+#foreach ($column in $columns)
+#if($column.query)
+    $column.javaField: undefined#if($foreach.count != $columns.size()),#end
+#end
+#end
+  },
+  rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+    $column.javaField: [
+      { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
+    ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ${functionName}鍒楄〃 */
+function getList() {
+  loading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+  queryParams.value.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  if (null != daterange${AttrName} && '' != daterange${AttrName}) {
+    queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
+    queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
+  }
+#end
+#end
+  list${BusinessName}(queryParams.value).then(response => {
+    ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+    loading.value = false;
+  });
+}
+
+/** 鏌ヨ${functionName}涓嬫媺鏍戠粨鏋� */
+async function getTreeselect() {
+  await list${BusinessName}().then(response => {
+    ${businessName}Options.value = [];
+    const data = { ${treeCode}: 0, ${treeName}: '椤剁骇鑺傜偣', children: [] };
+    data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+    ${businessName}Options.value.push(data);
+  });
+}
+
+// 鍙栨秷鎸夐挳
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+  form.value = {
+#foreach ($column in $columns)
+#if($column.htmlType == "radio")
+    $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
+
+#elseif($column.htmlType == "checkbox")
+    $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+  };
+  proxy.resetForm("${businessName}Ref");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+  getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  daterange${AttrName}.value = [];
+#end
+#end
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+async function handleAdd(row) {
+  reset();
+  await getTreeselect();
+  if (row != null && row.${treeCode}) {
+    form.value.${treeParentCode} = row.${treeCode};
+  } else {
+    form.value.${treeParentCode} = 0;
+  }
+  open.value = true;
+  title.value = "娣诲姞${functionName}";
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+async function handleUpdate(row) {
+  loading.value = true;
+  reset();
+  await getTreeselect();
+  if (row != null) {
+    form.value.${treeParentCode} = row.${treeCode};
+  }
+  get${BusinessName}(row.${pkColumn.javaField}).then(response => {
+    loading.value = false;
+    form.value = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+    form.value.$column.javaField = form.value.${column.javaField}.split(",");
+#end
+#end
+    open.value = true;
+    title.value = "淇敼${functionName}";
+  });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+  proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
+    if (valid) {
+      buttonLoading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+      form.value.$column.javaField = form.value.${column.javaField}.join(",");
+#end
+#end
+      if (form.value.${pkColumn.javaField} != null) {
+        update${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+          open.value = false;
+          getList();
+        }).finally(() => {
+          buttonLoading.value = false;
+        });
+      } else {
+        add${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+          open.value = false;
+          getList();
+        }).finally(() => {
+          buttonLoading.value = false;
+        });
+      }
+    }
+  });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+  proxy.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + row.${pkColumn.javaField} + '"鐨勬暟鎹」锛�').then(function() {
+    loading.value = true;
+    return del${BusinessName}(row.${pkColumn.javaField});
+  }).then(() => {
+    loading.value = false;
+    getList();
+    proxy.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+  }).finally(() => {
+    loading.value = false;
+  });
+}
+
+getList();
+</script>
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
new file mode 100644
index 0000000..6487f0f
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
@@ -0,0 +1,577 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input" || $column.htmlType == "textarea")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="璇疯緭鍏�${comment}"
+          clearable
+          size="small"
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable size="small">
+          <el-option
+            v-for="dict in ${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable size="small">
+          <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable size="small"
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="YYYY-MM-DD"
+          placeholder="閫夋嫨${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          size="small"
+          style="width: 240px"
+          value-format="YYYY-MM-DD"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="寮�濮嬫棩鏈�"
+          end-placeholder="缁撴潫鏃ユ湡"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <el-form-item>
+        <el-button type="primary" icon="Search" size="mini" @click="handleQuery">鎼滅储</el-button>
+        <el-button icon="Refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >鏂板</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="Edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['${moduleName}:${businessName}:edit']"
+        >淇敼</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="Delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['${moduleName}:${businessName}:remove']"
+        >鍒犻櫎</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="Download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['${moduleName}:${businessName}:export']"
+        >瀵煎嚭</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+      <el-table-column label="${comment}" align="center" prop="${javaField}" v-if="${column.list}"/>
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+#elseif($column.list && $column.dictType && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template #default="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+#elseif($column.list && "" != $javaField)
+      <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+      <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="Edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:edit']"
+          >淇敼</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="Delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:remove']"
+          >鍒犻櫎</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      v-model:p:page="queryParams.pageNum"
+      v-model:p:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}">
+          <imageUpload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}">
+          <fileUpload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):value="parseInt(dict.value)"#else:value="dict.value"#end
+
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+            <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in ${dictType}"
+              :key="dict.value"
+              #if($column.javaType == "Integer" || $column.javaType == "Long"):label="parseInt(dict.value)"#else:label="dict.value"#end
+
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable size="small"
+            v-model="form.${field}"
+            type="datetime"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            placeholder="閫夋嫨${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+        </el-form-item>
+#end
+#end
+#end
+#if($table.sub)
+        <el-divider content-position="center">${subTable.functionName}淇℃伅</el-divider>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" icon="Plus" size="mini" @click="handleAdd${subClassName}">娣诲姞</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" icon="Delete" size="mini" @click="handleDelete${subClassName}">鍒犻櫎</el-button>
+          </el-col>
+        </el-row>
+        <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
+          <el-table-column type="selection" width="50" align="center" />
+          <el-table-column label="搴忓彿" align="center" prop="index" width="50"/>
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+          <el-table-column label="$comment" prop="${javaField}">
+            <template #default="scope">
+              <el-input v-model="scope.row.$javaField" placeholder="璇疯緭鍏�$comment" />
+            </template>
+          </el-table-column>
+#end
+#end
+        </el-table>
+#end
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button>
+          <el-button @click="cancel">鍙� 娑�</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="${BusinessName}">
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+const { proxy } = getCurrentInstance();
+#if(${dicts} != '')
+#set($dictsNoSymbol=$dicts.replace("'", ""))
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
+#end
+
+const ${businessName}List = ref([]);
+#if($table.sub)
+const ${subclassName}List = ref([]);
+#end
+const open = ref(false);
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+#if($table.sub)
+const checked${subClassName} = ref([]);
+#end
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const title = ref("");
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+const daterange${AttrName} = ref([]);
+#end
+#end
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+#foreach ($column in $columns)
+#if($column.query)
+    $column.javaField: undefined#if($foreach.count != $columns.size()),#end
+#end
+#end
+  },
+  rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+    $column.javaField: [
+      { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select")"change"#else"blur"#end }
+    ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+  }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ${functionName}鍒楄〃 */
+function getList() {
+  loading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+  queryParams.value.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  if (null != daterange${AttrName} && '' != daterange${AttrName}) {
+    queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
+    queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
+  }
+#end
+#end
+  list${BusinessName}(queryParams.value).then(response => {
+    ${businessName}List.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+// 鍙栨秷鎸夐挳
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+  form.value = {
+#foreach ($column in $columns)
+#if($column.htmlType == "radio")
+    $column.javaField: #if($column.javaType == "Integer" || $column.javaType == "Long")0#else"0"#end#if($foreach.count != $columns.size()),#end
+#elseif($column.htmlType == "checkbox")
+    $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+    $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+  };
+#if($table.sub)
+  ${subclassName}List.value = [];
+#end
+  proxy.resetForm("${businessName}Ref");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+  daterange${AttrName}.value = [];
+#end
+#end
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 澶氶�夋閫変腑鏁版嵁
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.${pkColumn.javaField});
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+  reset();
+  open.value = true;
+  title.value = "娣诲姞${functionName}";
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+  loading.value = true
+  reset();
+  const ${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
+  get${BusinessName}(${pkColumn.javaField}).then(response => {
+    loading.value = false;
+    form.value = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+    form.value.$column.javaField = form.value.${column.javaField}.split(",");
+#end
+#end
+#if($table.sub)
+    ${subclassName}List.value = response.data.${subclassName}List;
+#end
+    open.value = true;
+    title.value = "淇敼${functionName}";
+  });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+  proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
+    if (valid) {
+      buttonLoading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+      form.value.$column.javaField = form.value.${column.javaField}.join(",");
+#end
+#end
+#if($table.sub)
+      form.value.${subclassName}List = ${subclassName}List.value;
+#end
+      if (form.value.${pkColumn.javaField} != null) {
+        update${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+          open.value = false;
+          getList();
+        }).finally(() => {
+          buttonLoading.value = false;
+        });
+      } else {
+        add${BusinessName}(form.value).then(response => {
+          proxy.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+          open.value = false;
+          getList();
+        }).finally(() => {
+          buttonLoading.value = false;
+        });
+      }
+    }
+  });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+  const ${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
+  proxy.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + ${pkColumn.javaField}s + '"鐨勬暟鎹」锛�').then(function() {
+    loading.value = true;
+    return del${BusinessName}(${pkColumn.javaField}s);
+  }).then(() => {
+    loading.value = true;
+    getList();
+    proxy.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+  }).finally(() => {
+    loading.value = false;
+  });
+}
+
+#if($table.sub)
+/** ${subTable.functionName}搴忓彿 */
+function row${subClassName}Index({ row, rowIndex }) {
+  row.index = rowIndex + 1;
+}
+
+/** ${subTable.functionName}娣诲姞鎸夐挳鎿嶄綔 */
+function handleAdd${subClassName}() {
+  let obj = {};
+#foreach($column in $subTable.columns)
+#if($column.pk || $column.javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+  obj.$column.javaField = "";
+#end
+#end
+  ${subclassName}List.value.push(obj);
+}
+
+/** ${subTable.functionName}鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete${subClassName}() {
+  if (checked${subClassName}.value.length == 0) {
+    proxy.#[[$modal]]#.msgError("璇峰厛閫夋嫨瑕佸垹闄ょ殑${subTable.functionName}鏁版嵁");
+  } else {
+    const ${subclassName}s = ${subclassName}List.value;
+    const checked${subClassName}s = checked${subClassName}.value;
+    ${subclassName}List.value = ${subclassName}s.filter(function(item) {
+      return checked${subClassName}s.indexOf(item.index) == -1
+    });
+  }
+}
+
+/** 澶嶉�夋閫変腑鏁版嵁 */
+function handle${subClassName}SelectionChange(selection) {
+  checked${subClassName}.value = selection.map(item => item.index)
+}
+
+#end
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+  proxy.download('${moduleName}/${businessName}/export', {
+    ...queryParams.value
+  }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
+}
+
+getList();
+</script>
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt
new file mode 100644
index 0000000..99239bb
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt
@@ -0,0 +1 @@
+如果使用的是RuoYi-Vue3前端,那么需要覆盖一下此目录的模板index.vue.vm、index-tree.vue.vm文件到上级vue目录。
\ No newline at end of file
diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml
index a87b3ef..3c13d35 100644
--- a/ruoyi-job/pom.xml
+++ b/ruoyi-job/pom.xml
@@ -31,7 +31,7 @@
 
         <dependency>
             <groupId>com.yomahub</groupId>
-            <artifactId>tlog-xxl-job</artifactId>
+            <artifactId>tlog-xxljob-spring-boot-starter</artifactId>
         </dependency>
 
     </dependencies>
diff --git a/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java b/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java
index 2df063e..e051ff0 100644
--- a/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java
+++ b/ruoyi-job/src/main/java/com/ruoyi/job/config/XxlJobConfig.java
@@ -2,7 +2,6 @@
 
 import com.ruoyi.job.config.properties.XxlJobProperties;
 import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
-import com.yomahub.tlog.springboot.lifecircle.TLogXxljobEnhanceInit;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -40,9 +39,4 @@
         return xxlJobSpringExecutor;
     }
 
-    @Bean
-    public TLogXxljobEnhanceInit tLogXxljobEnhanceInit(){
-        return new TLogXxljobEnhanceInit();
-    }
-
-}
\ No newline at end of file
+}
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
index 2b230bf..aa855a3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
@@ -3,6 +3,7 @@
 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 io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -10,6 +11,7 @@
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.Size;
+
 
 /**
  * 閫氱煡鍏憡琛� sys_notice
@@ -32,6 +34,7 @@
     /**
      * 鍏憡鏍囬
      */
+    @Xss(message = "鍏憡鏍囬涓嶈兘鍖呭惈鑴氭湰瀛楃")
     @ApiModelProperty(value = "鍏憡鏍囬")
     @NotBlank(message = "鍏憡鏍囬涓嶈兘涓虹┖")
     @Size(min = 0, max = 50, message = "鍏憡鏍囬涓嶈兘瓒呰繃50涓瓧绗�")
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
index ff081ce..775da2b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java
@@ -22,7 +22,7 @@
      * 涓诲缓
      */
     @TableId(value = "oss_config_id")
-    private Integer ossConfigId;
+    private Long ossConfigId;
 
     /**
      * 閰嶇疆key
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
index f2770ab..c48ae5b 100644
--- 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
@@ -17,28 +17,6 @@
 public class SysOssBo extends BaseEntity {
 
     /**
-     * 鍒嗛〉澶у皬
-     */
-    @ApiModelProperty("鍒嗛〉澶у皬")
-    private Integer pageSize;
-    /**
-     * 褰撳墠椤垫暟
-     */
-    @ApiModelProperty("褰撳墠椤垫暟")
-    private Integer pageNum;
-    /**
-     * 鎺掑簭鍒�
-     */
-    @ApiModelProperty("鎺掑簭鍒�")
-    private String orderByColumn;
-    /**
-     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
-     */
-    @ApiModelProperty(value = "鎺掑簭鐨勬柟鍚�", example = "asc,desc")
-    private String isAsc;
-
-
-    /**
      * 鏂囦欢鍚�
      */
     @ApiModelProperty("鏂囦欢鍚�")
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
index 9b8b378..9a66e38 100644
--- 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
@@ -102,29 +102,4 @@
     @ApiModelProperty(value = "鎵╁睍瀛楁")
     private String ext1;
 
-
-    /**
-     * 鍒嗛〉澶у皬
-     */
-    @ApiModelProperty("鍒嗛〉澶у皬")
-    private Integer pageSize;
-
-    /**
-     * 褰撳墠椤垫暟
-     */
-    @ApiModelProperty("褰撳墠椤垫暟")
-    private Integer pageNum;
-
-    /**
-     * 鎺掑簭鍒�
-     */
-    @ApiModelProperty("鎺掑簭鍒�")
-    private String orderByColumn;
-
-    /**
-     * 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc
-     */
-    @ApiModelProperty(value = "鎺掑簭鐨勬柟鍚�", example = "asc,desc")
-    private String isAsc;
-
 }
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
index c655110..9bd21d3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java
@@ -10,6 +10,7 @@
 import com.ruoyi.common.utils.LoginUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
+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;
@@ -40,9 +41,9 @@
     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 = SpringUtils.getBean(ISysConfigService.class)
-            .selectConfigByKey("sys.user.initPassword");
+        this.password = SecurityUtils.encryptPassword(initPassword);
         this.isUpdateSupport = isUpdateSupport;
         this.operName = LoginUtils.getUsername();
     }
@@ -54,12 +55,14 @@
             // 楠岃瘉鏄惁瀛樺湪杩欎釜鐢ㄦ埛
             if (StringUtils.isNull(user)) {
                 user = BeanUtil.toBean(userVo, SysUser.class);
-                user.setPassword(SecurityUtils.encryptPassword(password));
+                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) {
+                ValidatorUtils.validate(user);
                 user.setUpdateBy(operName);
                 userService.updateUser(user);
                 successNum++;
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
index 051085c..317be7e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -1,5 +1,7 @@
 package com.ruoyi.system.mapper;
 
+import com.ruoyi.common.annotation.DataColumn;
+import com.ruoyi.common.annotation.DataPermission;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
 import org.apache.ibatis.annotations.Param;
@@ -19,6 +21,9 @@
      * @param dept 閮ㄩ棬淇℃伅
      * @return 閮ㄩ棬淇℃伅闆嗗悎
      */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id")
+    })
     List<SysDept> selectDeptList(SysDept dept);
 
     /**
@@ -28,7 +33,7 @@
      * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
      * @return 閫変腑閮ㄩ棬鍒楄〃
      */
-    List<Integer> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
+    List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
 
     /**
      * 淇敼瀛愬厓绱犲叧绯�
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
index 50a5c75..2e305cf 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
@@ -18,7 +18,7 @@
      * @param userId 鐢ㄦ埛ID
      * @return 閫変腑宀椾綅ID鍒楄〃
      */
-    List<Integer> selectPostListByUserId(Long userId);
+    List<Long> selectPostListByUserId(Long userId);
 
     /**
      * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
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
index eb44006..d2721ee 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
@@ -1,6 +1,8 @@
 package com.ruoyi.system.mapper;
 
 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.domain.entity.SysRole;
 import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
 import org.apache.ibatis.annotations.Param;
@@ -14,6 +16,9 @@
  */
 public interface SysRoleMapper extends BaseMapperPlus<SysRole> {
 
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id")
+    })
     Page<SysRole> selectPageRoleList(@Param("page") Page<SysRole> page, @Param("role") SysRole role);
 
     /**
@@ -22,6 +27,9 @@
      * @param role 瑙掕壊淇℃伅
      * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
      */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id")
+    })
     List<SysRole> selectRoleList(SysRole role);
 
     /**
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
index e930d87..1a07f7f 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -1,6 +1,8 @@
 package com.ruoyi.system.mapper;
 
 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.domain.entity.SysUser;
 import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
 import org.apache.ibatis.annotations.Param;
@@ -14,6 +16,10 @@
  */
 public interface SysUserMapper extends BaseMapperPlus<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("user") SysUser user);
 
     /**
@@ -22,6 +28,10 @@
      * @param sysUser 鐢ㄦ埛淇℃伅
      * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
      */
+    @DataPermission({
+        @DataColumn(key = "deptName", value = "d.dept_id"),
+        @DataColumn(key = "userName", value = "u.user_id")
+    })
     List<SysUser> selectUserList(SysUser sysUser);
 
     /**
@@ -30,6 +40,10 @@
      * @param user 鐢ㄦ埛淇℃伅
      * @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("user") SysUser user);
 
     /**
@@ -38,6 +52,10 @@
      * @param user 鐢ㄦ埛淇℃伅
      * @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("user") SysUser user);
 
     /**
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
index fe28387..b723389 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysConfig;
 
@@ -14,7 +15,7 @@
 public interface ISysConfigService extends IService<SysConfig> {
 
 
-    TableDataInfo<SysConfig> selectPageConfigList(SysConfig config);
+    TableDataInfo<SysConfig> selectPageConfigList(SysConfig config, PageQuery pageQuery);
 
     /**
      * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
index bd8c5ff..292d43c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
@@ -34,7 +34,7 @@
      * @param roleId 瑙掕壊ID
      * @return 閫変腑閮ㄩ棬鍒楄〃
      */
-    List<Integer> selectDeptListByRoleId(Long roleId);
+    List<Long> selectDeptListByRoleId(Long roleId);
 
     /**
      * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
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
index ce6898e..22259c3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.page.TableDataInfo;
 
@@ -14,7 +15,7 @@
 public interface ISysDictDataService extends IService<SysDictData> {
 
 
-    TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData);
+    TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData, PageQuery pageQuery);
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
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
index 9599c4f..ba27398 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.domain.entity.SysDictType;
 import com.ruoyi.common.core.page.TableDataInfo;
@@ -15,7 +16,7 @@
 public interface ISysDictTypeService extends IService<SysDictType> {
 
 
-    TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType);
+    TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType, PageQuery pageQuery);
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
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
index 5d4a66e..892a5af 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysLogininfor;
 
@@ -14,7 +15,7 @@
 public interface ISysLogininforService extends IService<SysLogininfor> {
 
 
-    TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor);
+    TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor, PageQuery pageQuery);
 
     /**
      * 鏂板绯荤粺鐧诲綍鏃ュ織
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
index 7db68da..6cd9468 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysNotice;
 
@@ -14,7 +15,7 @@
 public interface ISysNoticeService extends IService<SysNotice> {
 
 
-    TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice);
+    TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice, PageQuery pageQuery);
 
     /**
      * 鏌ヨ鍏憡淇℃伅
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
index 531f639..b23f129 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysOperLog;
 
@@ -13,7 +14,7 @@
  */
 public interface ISysOperLogService extends IService<SysOperLog> {
 
-    TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog);
+    TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog, PageQuery pageQuery);
 
     /**
      * 鏂板鎿嶄綔鏃ュ織
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
index 9d9fd53..f29b65d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssConfigService.java
@@ -1,5 +1,6 @@
 package com.ruoyi.system.service;
 
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysOssConfig;
@@ -30,7 +31,7 @@
     /**
      * 鏌ヨ鍒楄〃
      */
-    TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo);
+    TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery);
 
 
     /**
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
index 948e8f7..866f2c4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java
@@ -1,5 +1,6 @@
 package com.ruoyi.system.service;
 
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysOss;
@@ -16,7 +17,7 @@
  */
 public interface ISysOssService extends IServicePlus<SysOss, SysOssVo> {
 
-    TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss);
+    TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
 
     SysOss upload(MultipartFile file);
 
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
index a049928..97a0e06 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysPost;
 
@@ -14,7 +15,7 @@
 public interface ISysPostService extends IService<SysPost> {
 
 
-    TableDataInfo<SysPost> selectPagePostList(SysPost post);
+    TableDataInfo<SysPost> selectPagePostList(SysPost post, PageQuery pageQuery);
 
     /**
      * 鏌ヨ宀椾綅淇℃伅闆嗗悎
@@ -45,7 +46,7 @@
      * @param userId 鐢ㄦ埛ID
      * @return 閫変腑宀椾綅ID鍒楄〃
      */
-    List<Integer> selectPostListByUserId(Long userId);
+    List<Long> selectPostListByUserId(Long userId);
 
     /**
      * 鏍¢獙宀椾綅鍚嶇О
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
index d5838a8..37f0071 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.system.domain.SysUserRole;
@@ -16,7 +17,7 @@
 public interface ISysRoleService extends IService<SysRole> {
 
 
-    TableDataInfo<SysRole> selectPageRoleList(SysRole role);
+    TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery);
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
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
index a901e0a..508f3c4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.service.UserService;
@@ -15,7 +16,7 @@
 public interface ISysUserService extends IService<SysUser>, UserService {
 
 
-    TableDataInfo<SysUser> selectPageUserList(SysUser user);
+    TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery);
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
@@ -31,7 +32,7 @@
      * @param user 鐢ㄦ埛淇℃伅
      * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
      */
-    TableDataInfo<SysUser> selectAllocatedList(SysUser user);
+    TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery);
 
     /**
      * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
@@ -39,7 +40,7 @@
      * @param user 鐢ㄦ埛淇℃伅
      * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
      */
-    TableDataInfo<SysUser> selectUnallocatedList(SysUser user);
+    TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery);
 
     /**
      * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
@@ -203,13 +204,4 @@
      */
     int deleteUserByIds(Long[] userIds);
 
-    /**
-     * 瀵煎叆鐢ㄦ埛鏁版嵁
-     *
-     * @param userList        鐢ㄦ埛鏁版嵁鍒楄〃
-     * @param isUpdateSupport 鏄惁鏇存柊鏀寔锛屽鏋滃凡瀛樺湪锛屽垯杩涜鏇存柊鏁版嵁
-     * @param operName        鎿嶄綔鐢ㄦ埛
-     * @return 缁撴灉
-     */
-    String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysDataScopeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysDataScopeService.java
new file mode 100644
index 0000000..34e2ea3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysDataScopeService.java
@@ -0,0 +1,24 @@
+package com.ruoyi.system.service;
+
+/**
+ * 閫氱敤 鏁版嵁鏉冮檺 鏈嶅姟
+ *
+ * @author Lion Li
+ */
+public interface SysDataScopeService {
+
+    /**
+     * 鑾峰彇瑙掕壊鑷畾涔夋潈闄�
+     * @param roleId 瑙掕壊id
+     * @return 閮ㄩ棬id缁�
+     */
+    String getRoleCustom(Long roleId);
+
+    /**
+     * 鑾峰彇閮ㄩ棬鍙婁互涓嬫潈闄�
+     * @param deptId 閮ㄩ棬id
+     * @return 閮ㄩ棬id缁�
+     */
+    String getDeptAndChild(Long deptId);
+
+}
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
index ebc208d..c9a8803 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
@@ -11,13 +12,14 @@
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.exception.user.CaptchaException;
 import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.exception.user.UserException;
 import com.ruoyi.common.utils.*;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 鐧诲綍鏍¢獙鏂规硶
@@ -56,21 +58,46 @@
         if (captchaOnOff) {
             validateCaptcha(username, code, uuid, request);
         }
+        // 鑾峰彇鐢ㄦ埛鐧诲綍閿欒娆℃暟(鍙嚜瀹氫箟闄愬埗绛栫暐 渚嬪: key + username + ip)
+        Integer errorNumber = RedisUtils.getCacheObject(Constants.LOGIN_ERROR + username);
+        // 閿佸畾鏃堕棿鍐呯櫥褰� 鍒欒涪鍑�
+        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
+            asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME), request);
+            throw new UserException("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
+        }
+
         SysUser user = userService.selectUserByUserName(username);
         if (StringUtils.isNull(user)) {
             log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", username);
-            throw new ServiceException("鐧诲綍鐢ㄦ埛锛�" + username + " 涓嶅瓨鍦�");
+            throw new UserException("user.not.exists", username);
         } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
             log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍒犻櫎.", username);
-            throw new ServiceException("瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛�" + username + " 宸茶鍒犻櫎");
+            throw new UserException("user.password.delete", username);
         } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
             log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", username);
-            throw new ServiceException("瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛�" + username + " 宸插仠鐢�");
+            throw new UserException("user.blocked", username);
         }
         if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
-            asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
-            throw new UserPasswordNotMatchException();
+            // 鏄惁绗竴娆�
+            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
+            // 杈惧埌瑙勫畾閿欒娆℃暟 鍒欓攣瀹氱櫥褰�
+            if (errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
+                RedisUtils.setCacheObject(Constants.LOGIN_ERROR + username, errorNumber, Constants.LOGIN_ERROR_LIMIT_TIME, TimeUnit.MINUTES);
+                asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME), request);
+                throw new UserException("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
+            } else {
+                // 鏈揪鍒拌瀹氶敊璇鏁� 鍒欓�掑
+                RedisUtils.setCacheObject(Constants.LOGIN_ERROR + username, errorNumber);
+                asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", errorNumber), request);
+                throw new UserException("user.password.retry.limit.count", errorNumber);
+            }
         }
+
+        // 鐧诲綍鎴愬姛 娓呯┖閿欒娆℃暟
+        RedisUtils.deleteObject(Constants.LOGIN_ERROR + username);
+        asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
+        recordLoginInfo(user.getUserId(), username);
+
         LoginUser loginUser = new LoginUser();
         loginUser.setUserId(user.getUserId());
         loginUser.setDeptId(user.getDeptId());
@@ -78,8 +105,6 @@
         loginUser.setMenuPermission(permissionService.getMenuPermission(user));
         loginUser.setRolePermission(permissionService.getRolePermission(user));
 
-		asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
-        recordLoginInfo(user.getUserId(), username);
         // 鐢熸垚token
         LoginUtils.loginByDevice(loginUser, UserType.SYS_USER, DeviceType.PC);
         return StpUtil.getTokenValue();
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
index bbd09a1..0b16029 100644
--- 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
@@ -1,16 +1,16 @@
 package com.ruoyi.system.service.impl;
 
 import cn.hutool.core.convert.Convert;
+import com.baomidou.dynamic.datasource.annotation.DS;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.annotation.DataSource;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.service.ConfigService;
-import com.ruoyi.common.enums.DataSourceType;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysConfig;
@@ -32,7 +32,7 @@
 public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysConfig, SysConfig> implements ISysConfigService, ConfigService {
 
     @Override
-    public TableDataInfo<SysConfig> selectPageConfigList(SysConfig config) {
+    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())
@@ -40,7 +40,8 @@
             .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 PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
+        Page<SysConfig> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -50,7 +51,7 @@
      * @return 鍙傛暟閰嶇疆淇℃伅
      */
     @Override
-    @DataSource(DataSourceType.MASTER)
+    @DS("master")
     public SysConfig selectConfigById(Long configId) {
         return baseMapper.selectById(configId);
     }
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
new file mode 100644
index 0000000..8439958
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java
@@ -0,0 +1,50 @@
+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.common.core.domain.entity.SysDept;
+import com.ruoyi.system.domain.SysRoleDept;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.system.mapper.SysRoleDeptMapper;
+import com.ruoyi.system.service.SysDataScopeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service("sdss")
+public class SysDataScopeServiceImpl implements SysDataScopeService {
+
+    @Autowired
+    private SysRoleDeptMapper roleDeptMapper;
+    @Autowired
+    private 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 list.stream().map(rd -> Convert.toStr(rd.getDeptId())).collect(Collectors.joining(","));
+        }
+        return null;
+    }
+
+    @Override
+    public String getDeptAndChild(Long deptId) {
+        List<SysDept> list = deptMapper.selectList(new LambdaQueryWrapper<SysDept>()
+            .select(SysDept::getDeptId)
+            .eq(SysDept::getDeptId, deptId)
+            .or()
+            .apply("find_in_set({0},ancestors)", deptId));
+        if (CollUtil.isNotEmpty(list)) {
+            return list.stream().map(d -> Convert.toStr(d.getDeptId())).collect(Collectors.joining(","));
+        }
+        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
index eccafb3..23c7d58 100644
--- 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
@@ -1,10 +1,10 @@
 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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.ruoyi.common.annotation.DataScope;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
@@ -46,8 +46,9 @@
      * @return 閮ㄩ棬淇℃伅闆嗗悎
      */
     @Override
-    @DataScope(deptAlias = "d")
     public List<SysDept> selectDeptList(SysDept dept) {
+//        return baseMapper.selectList();
+//        return baseMapper.selectList(new LambdaQueryWrapper<>());
         return baseMapper.selectDeptList(dept);
     }
 
@@ -59,7 +60,11 @@
      */
     @Override
     public List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts) {
-        return TreeBuildUtils.build(depts, (dept, tree) ->
+        if (CollUtil.isEmpty(depts)) {
+            return CollUtil.newArrayList();
+        }
+        Long parentId = depts.get(0).getParentId();
+        return TreeBuildUtils.build(depts, parentId, (dept, tree) ->
             tree.setId(dept.getDeptId())
                 .setParentId(dept.getParentId())
                 .setName(dept.getDeptName())
@@ -73,7 +78,7 @@
      * @return 閫変腑閮ㄩ棬鍒楄〃
      */
     @Override
-    public List<Integer> selectDeptListByRoleId(Long roleId) {
+    public List<Long> selectDeptListByRoleId(Long roleId) {
         SysRole role = roleMapper.selectById(roleId);
         return baseMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
     }
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
index d2ac2a0..7726ee0 100644
--- 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
@@ -1,11 +1,12 @@
 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.Constants;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.mapper.SysDictDataMapper;
@@ -23,13 +24,14 @@
 public class SysDictDataServiceImpl extends ServicePlusImpl<SysDictDataMapper, SysDictData, SysDictData> implements ISysDictDataService {
 
     @Override
-    public TableDataInfo<SysDictData> selectPageDictDataList(SysDictData dictData) {
+    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);
-        return PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
+        Page<SysDictData> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
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
index b520d41..1934f20 100644
--- 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
@@ -3,15 +3,16 @@
 import cn.hutool.core.collection.CollUtil;
 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.Constants;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.domain.entity.SysDictType;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 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.PageUtils;
 import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.mapper.SysDictDataMapper;
@@ -38,7 +39,7 @@
     private SysDictDataMapper dictDataMapper;
 
     @Override
-    public TableDataInfo<SysDictType> selectPageDictTypeList(SysDictType dictType) {
+    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())
@@ -46,7 +47,8 @@
             .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 PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
+        Page<SysDictType> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -189,7 +191,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int updateDictType(SysDictType dict) {
         SysDictType oldDict = getById(dict.getDictId());
         dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>()
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
index 0ce33be..487e811 100644
--- 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
@@ -3,11 +3,12 @@
 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.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.service.LogininforService;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.ip.AddressUtils;
@@ -87,7 +88,7 @@
     }
 
     @Override
-    public TableDataInfo<SysLogininfor> selectPageLogininforList(SysLogininfor logininfor) {
+    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())
@@ -95,7 +96,11 @@
             .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"));
-        return PageUtils.buildDataInfo(page(PageUtils.buildPage("info_id", "desc"), lqw));
+        if(StringUtils.isBlank(pageQuery.getOrderByColumn())) {
+            pageQuery.setOrderByColumn("info_id").setIsAsc("desc");
+        }
+        Page<SysLogininfor> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
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
index 9c3bfeb..a604a12 100644
--- 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
@@ -1,5 +1,6 @@
 package com.ruoyi.system.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.tree.Tree;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.ruoyi.common.constant.Constants;
@@ -157,7 +158,7 @@
                 router.setPath("/inner");
                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                 RouterVo children = new RouterVo();
-                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
+                String routerPath = innerLinkReplaceEach(menu.getPath());
                 children.setPath(routerPath);
                 children.setComponent(UserConstants.INNER_LINK);
                 children.setName(StringUtils.capitalize(routerPath));
@@ -178,7 +179,11 @@
      */
     @Override
     public List<Tree<Long>> buildMenuTreeSelect(List<SysMenu> menus) {
-        return TreeBuildUtils.build(menus, (menu, tree) ->
+        if (CollUtil.isEmpty(menus)) {
+            return CollUtil.newArrayList();
+        }
+        Long parentId = menus.get(0).getParentId();
+        return TreeBuildUtils.build(menus, parentId, (menu, tree) ->
             tree.setId(menu.getMenuId())
                 .setParentId(menu.getParentId())
                 .setName(menu.getMenuName())
@@ -297,7 +302,7 @@
         String routerPath = menu.getPath();
         // 鍐呴摼鎵撳紑澶栫綉鏂瑰紡
         if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
-            routerPath = StringUtils.replaceEach(routerPath, new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
+            routerPath = innerLinkReplaceEach(routerPath);
         }
         // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
         if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
@@ -415,4 +420,15 @@
     private boolean hasChild(List<SysMenu> list, SysMenu t) {
         return getChildList(list, t).size() > 0;
     }
+
+    /**
+     * 鍐呴摼鍩熷悕鐗规畩瀛楃鏇挎崲
+     *
+     * @return
+     */
+    public String innerLinkReplaceEach(String path)
+    {
+        return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS },
+                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
index b4f70d7..16bc852 100644
--- 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
@@ -1,9 +1,10 @@
 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.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysNotice;
 import com.ruoyi.system.mapper.SysNoticeMapper;
@@ -22,12 +23,13 @@
 public class SysNoticeServiceImpl extends ServicePlusImpl<SysNoticeMapper, SysNotice, SysNotice> implements ISysNoticeService {
 
     @Override
-    public TableDataInfo<SysNotice> selectPageNoticeList(SysNotice notice) {
+    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());
-        return PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
+        Page<SysNotice> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
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
index c08b634..9371d5a 100644
--- 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
@@ -3,11 +3,12 @@
 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.dto.OperLogDTO;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.service.OperLogService;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.ip.AddressUtils;
 import com.ruoyi.system.domain.SysOperLog;
@@ -44,7 +45,7 @@
     }
 
     @Override
-    public TableDataInfo<SysOperLog> selectPageOperLogList(SysOperLog operLog) {
+    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())
@@ -60,7 +61,11 @@
             .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"));
-        return PageUtils.buildDataInfo(page(PageUtils.buildPage("oper_id", "desc"), lqw));
+        if(StringUtils.isBlank(pageQuery.getOrderByColumn())) {
+            pageQuery.setOrderByColumn("oper_id").setIsAsc("desc");
+        }
+        Page<SysOperLog> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
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
index 9940bea..9c28301 100644
--- 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
@@ -5,14 +5,14 @@
 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.google.common.collect.Lists;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
-import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.JsonUtils;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.oss.constant.OssConstant;
@@ -67,9 +67,10 @@
     }
 
     @Override
-    public TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo) {
-        PagePlus<SysOssConfig, SysOssConfigVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
-        return PageUtils.buildDataInfo(result);
+    public TableDataInfo<SysOssConfigVo> queryPageList(SysOssConfigBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysOssConfig> lqw = buildQueryWrapper(bo);
+        Page<SysOssConfigVo> result = pageVo(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
     }
 
 
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
index c20cc4b..e062fbc 100644
--- 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
@@ -2,11 +2,11 @@
 
 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.mybatisplus.core.ServicePlusImpl;
-import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.oss.entity.UploadResult;
 import com.ruoyi.oss.factory.OssFactory;
@@ -33,9 +33,10 @@
 public class SysOssServiceImpl extends ServicePlusImpl<SysOssMapper, SysOss, SysOssVo> implements ISysOssService {
 
     @Override
-    public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo) {
-        PagePlus<SysOss, SysOssVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
-        return PageUtils.buildDataInfo(result);
+    public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
+        Page<SysOssVo> result = pageVo(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
     }
 
     private LambdaQueryWrapper<SysOss> buildQueryWrapper(SysOssBo bo) {
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
index 4e04f3a..058d7ed 100644
--- 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
@@ -1,11 +1,12 @@
 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.UserConstants;
+import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysPost;
 import com.ruoyi.system.domain.SysUserPost;
@@ -30,12 +31,13 @@
     private SysUserPostMapper userPostMapper;
 
     @Override
-    public TableDataInfo<SysPost> selectPagePostList(SysPost post) {
+    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());
-        return PageUtils.buildDataInfo(page(PageUtils.buildPage(), lqw));
+        Page<SysPost> page = page(pageQuery.build(), lqw);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -80,7 +82,7 @@
      * @return 閫変腑宀椾綅ID鍒楄〃
      */
     @Override
-    public List<Integer> selectPostListByUserId(Long userId) {
+    public List<Long> selectPostListByUserId(Long userId) {
         return baseMapper.selectPostListByUserId(userId);
     }
 
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
index 7d19191..d48cddd 100644
--- 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
@@ -1,15 +1,15 @@
 package com.ruoyi.system.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.ruoyi.common.annotation.DataScope;
+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.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.LoginUtils;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.system.domain.SysRoleDept;
@@ -44,9 +44,9 @@
     private SysRoleDeptMapper roleDeptMapper;
 
     @Override
-    @DataScope(deptAlias = "d")
-    public TableDataInfo<SysRole> selectPageRoleList(SysRole role) {
-        return PageUtils.buildDataInfo(baseMapper.selectPageRoleList(PageUtils.buildPage(), role));
+    public TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery) {
+        Page<SysRole> page = baseMapper.selectPageRoleList(pageQuery.build(), role);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -56,7 +56,6 @@
      * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
      */
     @Override
-    @DataScope(deptAlias = "d")
     public List<SysRole> selectRoleList(SysRole role) {
         return baseMapper.selectRoleList(role);
     }
@@ -215,7 +214,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int insertRole(SysRole role) {
         // 鏂板瑙掕壊淇℃伅
         baseMapper.insert(role);
@@ -229,7 +228,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int updateRole(SysRole role) {
         // 淇敼瑙掕壊淇℃伅
         baseMapper.updateById(role);
@@ -256,7 +255,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int authDataScope(SysRole role) {
         // 淇敼瑙掕壊淇℃伅
         baseMapper.updateById(role);
@@ -315,7 +314,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int deleteRoleById(Long roleId) {
         // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
         roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
@@ -331,7 +330,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int deleteRoleByIds(Long[] roleIds) {
         for (Long roleId : roleIds) {
             checkRoleAllowed(new SysRole(roleId));
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
index 7837b52..2963476 100644
--- 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
@@ -1,9 +1,11 @@
 package com.ruoyi.system.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.ruoyi.common.annotation.DataScope;
+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.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
@@ -11,7 +13,6 @@
 import com.ruoyi.common.core.service.UserService;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.LoginUtils;
-import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.spring.SpringUtils;
@@ -19,7 +20,6 @@
 import com.ruoyi.system.domain.SysUserPost;
 import com.ruoyi.system.domain.SysUserRole;
 import com.ruoyi.system.mapper.*;
-import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +29,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 鐢ㄦ埛 涓氬姟灞傚鐞�
@@ -51,13 +52,10 @@
     @Autowired
     private SysUserPostMapper userPostMapper;
 
-    @Autowired
-    private ISysConfigService configService;
-
     @Override
-    @DataScope(deptAlias = "d", userAlias = "u", isUser = true)
-    public TableDataInfo<SysUser> selectPageUserList(SysUser user) {
-        return PageUtils.buildDataInfo(baseMapper.selectPageUserList(PageUtils.buildPage(), user));
+    public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) {
+        Page<SysUser> page = baseMapper.selectPageUserList(pageQuery.build(), user);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -67,7 +65,6 @@
      * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
      */
     @Override
-    @DataScope(deptAlias = "d", userAlias = "u", isUser = true)
     public List<SysUser> selectUserList(SysUser user) {
         return baseMapper.selectUserList(user);
     }
@@ -79,9 +76,9 @@
      * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
      */
     @Override
-    @DataScope(deptAlias = "d", userAlias = "u", isUser = true)
-    public TableDataInfo<SysUser> selectAllocatedList(SysUser user) {
-        return PageUtils.buildDataInfo(baseMapper.selectAllocatedList(PageUtils.buildPage(), user));
+    public TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery) {
+        Page<SysUser> page = baseMapper.selectAllocatedList(pageQuery.build(), user);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -91,9 +88,9 @@
      * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
      */
     @Override
-    @DataScope(deptAlias = "d", userAlias = "u", isUser = true)
-    public TableDataInfo<SysUser> selectUnallocatedList(SysUser user) {
-        return PageUtils.buildDataInfo(baseMapper.selectUnallocatedList(PageUtils.buildPage(), user));
+    public TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery) {
+        Page<SysUser> page = baseMapper.selectUnallocatedList(pageQuery.build(), user);
+        return TableDataInfo.build(page);
     }
 
     /**
@@ -127,14 +124,10 @@
     @Override
     public String selectUserRoleGroup(String userName) {
         List<SysRole> list = roleMapper.selectRolesByUserName(userName);
-        StringBuilder idsStr = new StringBuilder();
-        for (SysRole role : list) {
-            idsStr.append(role.getRoleName()).append(",");
+        if (CollUtil.isEmpty(list)) {
+            return StringUtils.EMPTY;
         }
-        if (StringUtils.isNotEmpty(idsStr.toString())) {
-            return idsStr.substring(0, idsStr.length() - 1);
-        }
-        return idsStr.toString();
+        return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
     }
 
     /**
@@ -146,14 +139,10 @@
     @Override
     public String selectUserPostGroup(String userName) {
         List<SysPost> list = postMapper.selectPostsByUserName(userName);
-        StringBuilder idsStr = new StringBuilder();
-        for (SysPost post : list) {
-            idsStr.append(post.getPostName()).append(",");
+        if (CollUtil.isEmpty(list)) {
+            return StringUtils.EMPTY;
         }
-        if (StringUtils.isNotEmpty(idsStr.toString())) {
-            return idsStr.substring(0, idsStr.length() - 1);
-        }
-        return idsStr.toString();
+        return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
     }
 
     /**
@@ -243,7 +232,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int insertUser(SysUser user) {
         // 鏂板鐢ㄦ埛淇℃伅
         int rows = baseMapper.insert(user);
@@ -272,7 +261,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int updateUser(SysUser user) {
         Long userId = user.getUserId();
         // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
@@ -293,7 +282,7 @@
      * @param roleIds 瑙掕壊缁�
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void insertUserAuth(Long userId, Long[] roleIds) {
         userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
                 .eq(SysUserRole::getUserId, userId));
@@ -436,7 +425,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int deleteUserById(Long userId) {
         // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
         userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
@@ -452,7 +441,7 @@
      * @return 缁撴灉
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int deleteUserByIds(Long[] userIds) {
         for (Long userId : userIds) {
             checkUserAllowed(new SysUser(userId));
@@ -465,56 +454,4 @@
         return baseMapper.deleteBatchIds(ids);
     }
 
-    /**
-     * 瀵煎叆鐢ㄦ埛鏁版嵁
-     *
-     * @param userList        鐢ㄦ埛鏁版嵁鍒楄〃
-     * @param isUpdateSupport 鏄惁鏇存柊鏀寔锛屽鏋滃凡瀛樺湪锛屽垯杩涜鏇存柊鏁版嵁
-     * @param operName        鎿嶄綔鐢ㄦ埛
-     * @return 缁撴灉
-     */
-    @Override
-    public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) {
-        if (StringUtils.isNull(userList) || userList.size() == 0) {
-            throw new ServiceException("瀵煎叆鐢ㄦ埛鏁版嵁涓嶈兘涓虹┖锛�");
-        }
-        int successNum = 0;
-        int failureNum = 0;
-        StringBuilder successMsg = new StringBuilder();
-        StringBuilder failureMsg = new StringBuilder();
-        String password = configService.selectConfigByKey("sys.user.initPassword");
-        for (SysUser user : userList) {
-            try {
-                // 楠岃瘉鏄惁瀛樺湪杩欎釜鐢ㄦ埛
-                SysUser u = baseMapper.selectUserByUserName(user.getUserName());
-                if (StringUtils.isNull(u)) {
-                    user.setPassword(SecurityUtils.encryptPassword(password));
-                    user.setCreateBy(operName);
-                    this.insertUser(user);
-                    successNum++;
-                    successMsg.append("<br/>" + successNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆鎴愬姛");
-                } else if (isUpdateSupport) {
-                    user.setUpdateBy(operName);
-                    this.updateUser(user);
-                    successNum++;
-                    successMsg.append("<br/>" + successNum + "銆佽处鍙� " + user.getUserName() + " 鏇存柊鎴愬姛");
-                } else {
-                    failureNum++;
-                    failureMsg.append("<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 宸插瓨鍦�");
-                }
-            } catch (Exception e) {
-                failureNum++;
-                String msg = "<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆澶辫触锛�";
-                failureMsg.append(msg + e.getMessage());
-                log.error(msg, e);
-            }
-        }
-        if (failureNum > 0) {
-            failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細");
-            throw new ServiceException(failureMsg.toString());
-        } else {
-            successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�");
-        }
-        return successMsg.toString();
-    }
 }
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
index 889982a..8e9d1d7 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -42,17 +42,17 @@
         <if test="status != null and status != ''">
             AND status = #{status}
         </if>
-        <!-- 鏁版嵁鑼冨洿杩囨护 -->
-        <if test="params.dataScope != null and params.dataScope != ''">
-            AND ( ${params.dataScope} )
-        </if>
+<!--        &lt;!&ndash; 鏁版嵁鑼冨洿杩囨护 &ndash;&gt;-->
+<!--        <if test="params.dataScope != null and params.dataScope != ''">-->
+<!--            AND ( ${params.dataScope} )-->
+<!--        </if>-->
         order by d.parent_id, d.order_num
     </select>
 
-    <select id="selectDeptListByRoleId" resultType="Integer">
+    <select id="selectDeptListByRoleId" resultType="Long">
         select d.dept_id
         from sys_dept d
-        left join sys_role_dept rd on d.dept_id = rd.dept_id
+            left join sys_role_dept rd on d.dept_id = rd.dept_id
         where rd.role_id = #{roleId}
             <if test="deptCheckStrictly">
                 and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
index bfb5436..d441c73 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -27,33 +27,13 @@
         <result property="remark" column="remark"/>
     </resultMap>
 
-    <sql id="selectMenuVo">
-        select menu_id,
-               menu_name,
-               parent_id,
-               order_num,
-               path,
-               component,
-			   query,
-               is_frame,
-               is_cache,
-               menu_type,
-               visible,
-               status,
-               ifnull(perms, '') as perms,
-               icon,
-               create_time
-        from sys_menu
-    </sql>
-
-
     <select id="selectMenuTreeAll" resultMap="SysMenuResult">
         select distinct m.menu_id,
                         m.parent_id,
                         m.menu_name,
                         m.path,
                         m.component,
-						m.query,
+						m.`query`,
 						m.visible,
                         m.status,
                         ifnull(m.perms, '') as perms,
@@ -70,7 +50,7 @@
     </select>
 
     <select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
-        select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status,
+        select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status,
         ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
         from sys_menu m
         left join sys_role_menu rm on m.menu_id = rm.menu_id
@@ -95,7 +75,7 @@
                         m.menu_name,
                         m.path,
                         m.component,
-					    m.query,
+					    m.`query`,
                         m.visible,
                         m.status,
                         ifnull(m.perms, '') as perms,
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
index c009a6c..eebc0a7 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
@@ -29,7 +29,7 @@
         from sys_post
     </sql>
 
-    <select id="selectPostListByUserId" parameterType="Long" resultType="Integer">
+    <select id="selectPostListByUserId" parameterType="Long" resultType="Long">
         select p.post_id
         from sys_post p
                  left join sys_user_post up on up.post_id = p.post_id
@@ -45,4 +45,4 @@
         where u.user_name = #{userName}
     </select>
 
-</mapper> 
\ No newline at end of file
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
index 94b161b..c13bd68 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -60,10 +60,10 @@
         <if test="role.params.endTime != null and role.params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
             and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{role.params.endTime},'%y%m%d')
         </if>
-        <!-- 鏁版嵁鑼冨洿杩囨护 -->
-        <if test="role.params.dataScope != null and role.params.dataScope != ''">
-            AND ( ${role.params.dataScope} )
-        </if>
+<!--        &lt;!&ndash; 鏁版嵁鑼冨洿杩囨护 &ndash;&gt;-->
+<!--        <if test="role.params.dataScope != null and role.params.dataScope != ''">-->
+<!--            AND ( ${role.params.dataScope} )-->
+<!--        </if>-->
         order by r.role_sort
     </select>
 
@@ -88,10 +88,10 @@
         <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
             and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
         </if>
-        <!-- 鏁版嵁鑼冨洿杩囨护 -->
-        <if test="params.dataScope != null and params.dataScope != ''">
-            AND ( ${params.dataScope} )
-        </if>
+<!--        &lt;!&ndash; 鏁版嵁鑼冨洿杩囨护 &ndash;&gt;-->
+<!--        <if test="params.dataScope != null and params.dataScope != ''">-->
+<!--            AND ( ${params.dataScope} )-->
+<!--        </if>-->
         order by r.role_sort
     </select>
 
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 5d9a185..d9a927f 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -108,10 +108,10 @@
             AND (u.dept_id = #{user.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{user.deptId},
             ancestors) ))
         </if>
-        <!-- 鏁版嵁鑼冨洿杩囨护 -->
-        <if test="user.params.dataScope != null and user.params.dataScope != ''">
-            AND ( ${user.params.dataScope} )
-        </if>
+<!--        &lt;!&ndash; 鏁版嵁鑼冨洿杩囨护 &ndash;&gt;-->
+<!--        <if test="user.params.dataScope != null and user.params.dataScope != ''">-->
+<!--            AND ( ${user.params.dataScope} )-->
+<!--        </if>-->
     </select>
 
     <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
@@ -142,10 +142,10 @@
             AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId},
             ancestors) ))
         </if>
-        <!-- 鏁版嵁鑼冨洿杩囨护 -->
-        <if test="params.dataScope != null and params.dataScope != ''">
-            AND ( ${params.dataScope} )
-        </if>
+<!--        &lt;!&ndash; 鏁版嵁鑼冨洿杩囨护 &ndash;&gt;-->
+<!--        <if test="params.dataScope != null and params.dataScope != ''">-->
+<!--            AND ( ${params.dataScope} )-->
+<!--        </if>-->
     </select>
 
     <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json
index 2784ecc..8e1cc0f 100644
--- a/ruoyi-ui/package.json
+++ b/ruoyi-ui/package.json
@@ -38,7 +38,7 @@
   "dependencies": {
     "@riophae/vue-treeselect": "0.4.0",
     "axios": "0.24.0",
-    "clipboard": "2.0.6",
+    "clipboard": "2.0.8",
     "core-js": "3.19.1",
     "echarts": "4.9.0",
     "element-ui": "2.15.6",
@@ -65,7 +65,9 @@
     "@vue/cli-plugin-eslint": "4.4.6",
     "@vue/cli-service": "4.4.6",
     "babel-eslint": "10.1.0",
+    "babel-plugin-dynamic-import-node": "2.3.3",
     "chalk": "4.1.0",
+    "compression-webpack-plugin": "5.0.2",
     "connect": "3.6.6",
     "eslint": "7.15.0",
     "eslint-plugin-vue": "7.2.0",
diff --git a/ruoyi-ui/src/components/Crontab/day.vue b/ruoyi-ui/src/components/Crontab/day.vue
index bf9f566..fe3eaf0 100644
--- a/ruoyi-ui/src/components/Crontab/day.vue
+++ b/ruoyi-ui/src/components/Crontab/day.vue
@@ -2,7 +2,7 @@
 	<el-form size="small">
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="1">
-				鏃ワ紝鍏佽鐨勯�氶厤绗, - * / L M]
+				鏃ワ紝鍏佽鐨勯�氶厤绗, - * ? / L W]
 			</el-radio>
 		</el-form-item>
 
@@ -15,23 +15,23 @@
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="3">
 				鍛ㄦ湡浠�
-				<el-input-number v-model='cycle01' :min="0" :max="31" /> -
-				<el-input-number v-model='cycle02' :min="0" :max="31" /> 鏃�
+				<el-input-number v-model='cycle01' :min="1" :max="30" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 鏃�
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="4">
 				浠�
-				<el-input-number v-model='average01' :min="0" :max="31" /> 鍙峰紑濮嬶紝姣�
-				<el-input-number v-model='average02' :min="0" :max="31" /> 鏃ユ墽琛屼竴娆�
+				<el-input-number v-model='average01' :min="1" :max="30" /> 鍙峰紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 鏃ユ墽琛屼竴娆�
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="5">
 				姣忔湀
-				<el-input-number v-model='workday' :min="0" :max="31" /> 鍙锋渶杩戠殑閭d釜宸ヤ綔鏃�
+				<el-input-number v-model='workday' :min="1" :max="31" /> 鍙锋渶杩戠殑閭d釜宸ヤ綔鏃�
 			</el-radio>
 		</el-form-item>
 
@@ -72,31 +72,22 @@
 		// 鍗曢�夋寜閽�煎彉鍖栨椂
 		radioChange() {
 			('day rachange');
-			if (this.radioValue === 1) {
-				this.$emit('update', 'day', '*', 'day');
-				this.$emit('update', 'week', '?', 'day');
-				this.$emit('update', 'month', '*', 'day');
-			} else {
-				if (this.cron.hour === '*') {
-					this.$emit('update', 'hour', '0', 'day');
-				}
-				if (this.cron.min === '*') {
-					this.$emit('update', 'min', '0', 'day');
-				}
-				if (this.cron.second === '*') {
-					this.$emit('update', 'second', '0', 'day');
-				}
+			if (this.radioValue !== 2 && this.cron.week !== '?') {
+				this.$emit('update', 'week', '?', 'day')
 			}
 
 			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'day', '*');
+					break;
 				case 2:
 					this.$emit('update', 'day', '?');
 					break;
 				case 3:
-					this.$emit('update', 'day', this.cycle01 + '-' + this.cycle02);
+					this.$emit('update', 'day', this.cycleTotal);
 					break;
 				case 4:
-					this.$emit('update', 'day', this.average01 + '/' + this.average02);
+					this.$emit('update', 'day', this.averageTotal);
 					break;
 				case 5:
 					this.$emit('update', 'day', this.workday + 'W');
@@ -125,7 +116,7 @@
 		// 鏈�杩戝伐浣滄棩鍊煎彉鍖栨椂
 		workdayChange() {
 			if (this.radioValue == '5') {
-				this.$emit('update', 'day', this.workday + 'W');
+				this.$emit('update', 'day', this.workdayCheck + 'W');
 			}
 		},
 		// checkbox鍊煎彉鍖栨椂
@@ -133,19 +124,10 @@
 			if (this.radioValue == '7') {
 				this.$emit('update', 'day', this.checkboxString);
 			}
-		},
-		// 鐖剁粍浠朵紶閫掔殑week鍙戠敓鍙樺寲瑙﹀彂
-		weekChange() {
-			//鍒ゆ柇week鍊间笌day涓嶈兘鍚屾椂涓衡��?鈥�
-			if (this.cron.week == '?' && this.radioValue == '2') {
-				this.radioValue = '1';
-			} else if (this.cron.week !== '?' && this.radioValue != '2') {
-				this.radioValue = '2';
-			}
-		},
+		}
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'workdayCheck': 'workdayChange',
@@ -154,20 +136,20 @@
 	computed: {
 		// 璁$畻涓や釜鍛ㄦ湡鍊�
 		cycleTotal: function () {
-			this.cycle01 = this.checkNum(this.cycle01, 1, 31)
-			this.cycle02 = this.checkNum(this.cycle02, 1, 31)
-			return this.cycle01 + '-' + this.cycle02;
+			const cycle01 = this.checkNum(this.cycle01, 1, 30)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
+			return cycle01 + '-' + cycle02;
 		},
 		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
 		averageTotal: function () {
-			this.average01 = this.checkNum(this.average01, 1, 31)
-			this.average02 = this.checkNum(this.average02, 1, 31)
-			return this.average01 + '/' + this.average02;
+			const average01 = this.checkNum(this.average01, 1, 30)
+			const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
+			return average01 + '/' + average02;
 		},
 		// 璁$畻宸ヤ綔鏃ユ牸寮�
 		workdayCheck: function () {
-			this.workday = this.checkNum(this.workday, 1, 31)
-			return this.workday;
+			const workday = this.checkNum(this.workday, 1, 31)
+			return workday;
 		},
 		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
 		checkboxString: function () {
diff --git a/ruoyi-ui/src/components/Crontab/hour.vue b/ruoyi-ui/src/components/Crontab/hour.vue
index 5a1e146..29b8891 100644
--- a/ruoyi-ui/src/components/Crontab/hour.vue
+++ b/ruoyi-ui/src/components/Crontab/hour.vue
@@ -9,16 +9,16 @@
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="2">
 				鍛ㄦ湡浠�
-				<el-input-number v-model='cycle01' :min="0" :max="60" /> -
-				<el-input-number v-model='cycle02' :min="0" :max="60" /> 灏忔椂
+				<el-input-number v-model='cycle01' :min="0" :max="22" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 灏忔椂
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="3">
 				浠�
-				<el-input-number v-model='average01' :min="0" :max="60" /> 灏忔椂寮�濮嬶紝姣�
-				<el-input-number v-model='average02' :min="0" :max="60" /> 灏忔椂鎵ц涓�娆�
+				<el-input-number v-model='average01' :min="0" :max="22" /> 灏忔椂寮�濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 灏忔椂鎵ц涓�娆�
 			</el-radio>
 		</el-form-item>
 
@@ -51,23 +51,15 @@
 	methods: {
 		// 鍗曢�夋寜閽�煎彉鍖栨椂
 		radioChange() {
-			if (this.radioValue === 1) {
-				this.$emit('update', 'hour', '*', 'hour');
-				this.$emit('update', 'day', '*', 'hour');
-			} else {
-				if (this.cron.min === '*') {
-					this.$emit('update', 'min', '0', 'hour');
-				}
-				if (this.cron.second === '*') {
-					this.$emit('update', 'second', '0', 'hour');
-				}
-			}
 			switch (this.radioValue) {
+				case 1:
+        	this.$emit('update', 'hour', '*')
+        	break;
 				case 2:
-					this.$emit('update', 'hour', this.cycle01 + '-' + this.cycle02);
+					this.$emit('update', 'hour', this.cycleTotal);
 					break;
 				case 3:
-					this.$emit('update', 'hour', this.average01 + '/' + this.average02);
+					this.$emit('update', 'hour', this.averageTotal);
 					break;
 				case 4:
 					this.$emit('update', 'hour', this.checkboxString);
@@ -94,7 +86,7 @@
 		}
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'checkboxString': 'checkboxChange'
@@ -102,15 +94,15 @@
 	computed: {
 		// 璁$畻涓や釜鍛ㄦ湡鍊�
 		cycleTotal: function () {
-			this.cycle01 = this.checkNum(this.cycle01, 0, 23)
-			this.cycle02 = this.checkNum(this.cycle02, 0, 23)
-			return this.cycle01 + '-' + this.cycle02;
+			const cycle01 = this.checkNum(this.cycle01, 0, 22)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
+			return cycle01 + '-' + cycle02;
 		},
 		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
 		averageTotal: function () {
-			this.average01 = this.checkNum(this.average01, 0, 23)
-			this.average02 = this.checkNum(this.average02, 1, 23)
-			return this.average01 + '/' + this.average02;
+			const average01 = this.checkNum(this.average01, 0, 22)
+			const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0)
+			return average01 + '/' + average02;
 		},
 		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
 		checkboxString: function () {
diff --git a/ruoyi-ui/src/components/Crontab/index.vue b/ruoyi-ui/src/components/Crontab/index.vue
index 27b4ab3..3963df2 100644
--- a/ruoyi-ui/src/components/Crontab/index.vue
+++ b/ruoyi-ui/src/components/Crontab/index.vue
@@ -2,7 +2,12 @@
   <div>
     <el-tabs type="border-card">
       <el-tab-pane label="绉�" v-if="shouldHide('second')">
-        <CrontabSecond @update="updateCrontabValue" :check="checkNumber" ref="cronsecond" />
+        <CrontabSecond
+          @update="updateCrontabValue"
+          :check="checkNumber"
+          :cron="crontabValueObj"
+          ref="cronsecond"
+        />
       </el-tab-pane>
 
       <el-tab-pane label="鍒嗛挓" v-if="shouldHide('min')">
@@ -268,7 +273,7 @@
           insValue = 5;
         } else {
           this.$refs[refName].checkboxList = value.split(",");
-          insValue = 7;
+          insValue = 6;
         }
       } else if (name == "year") {
         if (value == "") {
diff --git a/ruoyi-ui/src/components/Crontab/min.vue b/ruoyi-ui/src/components/Crontab/min.vue
index 980c4e7..0a106ce 100644
--- a/ruoyi-ui/src/components/Crontab/min.vue
+++ b/ruoyi-ui/src/components/Crontab/min.vue
@@ -9,16 +9,16 @@
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="2">
 				鍛ㄦ湡浠�
-				<el-input-number v-model='cycle01' :min="0" :max="60" /> -
-				<el-input-number v-model='cycle02' :min="0" :max="60" /> 鍒嗛挓
+				<el-input-number v-model='cycle01' :min="0" :max="58" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 鍒嗛挓
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="3">
 				浠�
-				<el-input-number v-model='average01' :min="0" :max="60" /> 鍒嗛挓寮�濮嬶紝姣�
-				<el-input-number v-model='average02' :min="0" :max="60" /> 鍒嗛挓鎵ц涓�娆�
+				<el-input-number v-model='average01' :min="0" :max="58" /> 鍒嗛挓寮�濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 鍒嗛挓鎵ц涓�娆�
 			</el-radio>
 		</el-form-item>
 
@@ -52,19 +52,15 @@
 	methods: {
 		// 鍗曢�夋寜閽�煎彉鍖栨椂
 		radioChange() {
-			if (this.radioValue !== 1 && this.cron.second === '*') {
-				this.$emit('update', 'second', '0', 'min');
-			}
 			switch (this.radioValue) {
 				case 1:
 					this.$emit('update', 'min', '*', 'min');
-					this.$emit('update', 'hour', '*', 'min');
 					break;
 				case 2:
-					this.$emit('update', 'min', this.cycle01 + '-' + this.cycle02, 'min');
+					this.$emit('update', 'min', this.cycleTotal, 'min');
 					break;
 				case 3:
-					this.$emit('update', 'min', this.average01 + '/' + this.average02, 'min');
+					this.$emit('update', 'min', this.averageTotal, 'min');
 					break;
 				case 4:
 					this.$emit('update', 'min', this.checkboxString, 'min');
@@ -92,7 +88,7 @@
 
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'checkboxString': 'checkboxChange',
@@ -100,15 +96,15 @@
 	computed: {
 		// 璁$畻涓や釜鍛ㄦ湡鍊�
 		cycleTotal: function () {
-			this.cycle01 = this.checkNum(this.cycle01, 0, 59)
-			this.cycle02 = this.checkNum(this.cycle02, 0, 59)
-			return this.cycle01 + '-' + this.cycle02;
+			const cycle01 = this.checkNum(this.cycle01, 0, 58)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
+			return cycle01 + '-' + cycle02;
 		},
 		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
 		averageTotal: function () {
-			this.average01 = this.checkNum(this.average01, 0, 59)
-			this.average02 = this.checkNum(this.average02, 1, 59)
-			return this.average01 + '/' + this.average02;
+			const average01 = this.checkNum(this.average01, 0, 58)
+			const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
+			return average01 + '/' + average02;
 		},
 		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
 		checkboxString: function () {
diff --git a/ruoyi-ui/src/components/Crontab/month.vue b/ruoyi-ui/src/components/Crontab/month.vue
index 619d1e7..fd0ac38 100644
--- a/ruoyi-ui/src/components/Crontab/month.vue
+++ b/ruoyi-ui/src/components/Crontab/month.vue
@@ -9,16 +9,16 @@
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="2">
 				鍛ㄦ湡浠�
-				<el-input-number v-model='cycle01' :min="1" :max="12" /> -
-				<el-input-number v-model='cycle02' :min="1" :max="12" /> 鏈�
+				<el-input-number v-model='cycle01' :min="1" :max="11" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 鏈�
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="3">
 				浠�
-				<el-input-number v-model='average01' :min="1" :max="12" /> 鏈堝紑濮嬶紝姣�
-				<el-input-number v-model='average02' :min="1" :max="12" /> 鏈堟湀鎵ц涓�娆�
+				<el-input-number v-model='average01' :min="1" :max="11" /> 鏈堝紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 鏈堟湀鎵ц涓�娆�
 			</el-radio>
 		</el-form-item>
 
@@ -51,29 +51,15 @@
 	methods: {
 		// 鍗曢�夋寜閽�煎彉鍖栨椂
 		radioChange() {
-			if (this.radioValue === 1) {
-				this.$emit('update', 'month', '*');
-				this.$emit('update', 'year', '*');
-			} else {
-				if (this.cron.day === '*') {
-					this.$emit('update', 'day', '0', 'month');
-				}
-				if (this.cron.hour === '*') {
-					this.$emit('update', 'hour', '0', 'month');
-				}
-				if (this.cron.min === '*') {
-					this.$emit('update', 'min', '0', 'month');
-				}
-				if (this.cron.second === '*') {
-					this.$emit('update', 'second', '0', 'month');
-				}
-			}
 			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'month', '*');
+					break;
 				case 2:
-					this.$emit('update', 'month', this.cycle01 + '-' + this.cycle02);
+					this.$emit('update', 'month', this.cycleTotal);
 					break;
 				case 3:
-					this.$emit('update', 'month', this.average01 + '/' + this.average02);
+					this.$emit('update', 'month', this.averageTotal);
 					break;
 				case 4:
 					this.$emit('update', 'month', this.checkboxString);
@@ -100,7 +86,7 @@
 		}
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'checkboxString': 'checkboxChange'
@@ -108,15 +94,15 @@
 	computed: {
 		// 璁$畻涓や釜鍛ㄦ湡鍊�
 		cycleTotal: function () {
-			this.cycle01 = this.checkNum(this.cycle01, 1, 12)
-			this.cycle02 = this.checkNum(this.cycle02, 1, 12)
-			return this.cycle01 + '-' + this.cycle02;
+			const cycle01 = this.checkNum(this.cycle01, 1, 11)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
+			return cycle01 + '-' + cycle02;
 		},
 		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
 		averageTotal: function () {
-			this.average01 = this.checkNum(this.average01, 1, 12)
-			this.average02 = this.checkNum(this.average02, 1, 12)
-			return this.average01 + '/' + this.average02;
+			const average01 = this.checkNum(this.average01, 1, 11)
+			const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0)
+			return average01 + '/' + average02;
 		},
 		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
 		checkboxString: function () {
diff --git a/ruoyi-ui/src/components/Crontab/result.vue b/ruoyi-ui/src/components/Crontab/result.vue
index 07b963b..aea6e0e 100644
--- a/ruoyi-ui/src/components/Crontab/result.vue
+++ b/ruoyi-ui/src/components/Crontab/result.vue
@@ -179,7 +179,7 @@
 							// 鑾峰彇杈惧埌鏉′欢鐨勬棩鏈熸槸鏄熸湡X
 							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
 							// 褰撴槦鏈熸棩鏃�
-							if (thisWeek == 0) {
+							if (thisWeek == 1) {
 								// 鍏堟壘涓嬩竴涓棩锛屽苟鍒ゆ柇鏄惁涓烘湀搴�
 								DD++;
 								thisDD = DD < 10 ? '0' + DD : DD;
@@ -187,7 +187,7 @@
 								if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 									DD -= 3;
 								}
-							} else if (thisWeek == 6) {
+							} else if (thisWeek == 7) {
 								// 褰撴槦鏈�6鏃跺彧闇�鍒ゆ柇涓嶆槸1鍙峰氨鍙繘琛屾搷浣�
 								if (this.dayRuleSup !== 1) {
 									DD--;
@@ -200,7 +200,7 @@
 							// 鑾峰彇褰撳墠鏃ユ湡鏄睘浜庢槦鏈熷嚑
 							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
 							// 鏍¢獙褰撳墠鏄熸湡鏄惁鍦ㄦ槦鏈熸睜锛坉ayRuleSup锛変腑
-							if (Array.indexOf(this.dayRuleSup, thisWeek) < 0) {
+							if (this.dayRuleSup.indexOf(thisWeek) < 0) {
 								// 濡傛灉鍒拌揪鏈�澶у�兼椂
 								if (Di == DDate.length - 1) {
 									resetDay();
@@ -385,7 +385,7 @@
 				} else if (rule.indexOf('#') >= 0) {
 					this.dayRule = 'assWeek';
 					let matchRule = rule.match(/[0-9]{1}/g);
-					this.dayRuleSup = [Number(matchRule[0]), Number(matchRule[1])];
+					this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])];
 					this.dateArr[3] = [1];
 					if (this.dayRuleSup[1] == 7) {
 						this.dayRuleSup[1] = 0;
@@ -400,14 +400,6 @@
 				} else if (rule !== '*' && rule !== '?') {
 					this.dayRule = 'weekDay';
 					this.dayRuleSup = this.getAssignArr(rule)
-				}
-				// 濡傛灉weekDay鏃跺皢7璋冩暣涓�0銆恮eek鍊�0鍗虫槸鏄熸湡鏃ャ��
-				if (this.dayRule == 'weekDay') {
-					for (let i = 0; i < this.dayRuleSup.length; i++) {
-						if (this.dayRuleSup[i] == 7) {
-							this.dayRuleSup[i] = 0;
-						}
-					}
 				}
 			}
 		},
@@ -543,14 +535,15 @@
 			if (type == undefined) {
 				return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
 			} else if (type == 'week') {
-				return week;
+				// 鍦╭uartz涓� 1涓烘槦鏈熸棩
+				return week + 1;
 			}
 		},
 		// 妫�鏌ユ棩鏈熸槸鍚﹀瓨鍦�
 		checkDate(value) {
 			let time = new Date(value);
 			let format = this.formatDate(time)
-			return value == format ? true : false;
+			return value === format;
 		}
 	},
 	watch: {
diff --git a/ruoyi-ui/src/components/Crontab/second.vue b/ruoyi-ui/src/components/Crontab/second.vue
index 0fdf338..e7b7761 100644
--- a/ruoyi-ui/src/components/Crontab/second.vue
+++ b/ruoyi-ui/src/components/Crontab/second.vue
@@ -9,16 +9,16 @@
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="2">
 				鍛ㄦ湡浠�
-				<el-input-number v-model='cycle01' :min="0" :max="60" /> -
-				<el-input-number v-model='cycle02' :min="0" :max="60" /> 绉�
+				<el-input-number v-model='cycle01' :min="0" :max="58" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 绉�
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="3">
 				浠�
-				<el-input-number v-model='average01' :min="0" :max="60" /> 绉掑紑濮嬶紝姣�
-				<el-input-number v-model='average02' :min="0" :max="60" /> 绉掓墽琛屼竴娆�
+				<el-input-number v-model='average01' :min="0" :max="58" /> 绉掑紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 绉掓墽琛屼竴娆�
 			</el-radio>
 		</el-form-item>
 
@@ -54,13 +54,12 @@
 			switch (this.radioValue) {
 				case 1:
 					this.$emit('update', 'second', '*', 'second');
-					this.$emit('update', 'min', '*', 'second');
 					break;
 				case 2:
-					this.$emit('update', 'second', this.cycle01 + '-' + this.cycle02);
+					this.$emit('update', 'second', this.cycleTotal);
 					break;
 				case 3:
-					this.$emit('update', 'second', this.average01 + '/' + this.average02);
+					this.$emit('update', 'second', this.averageTotal);
 					break;
 				case 4:
 					this.$emit('update', 'second', this.checkboxString);
@@ -84,25 +83,10 @@
 			if (this.radioValue == '4') {
 				this.$emit('update', 'second', this.checkboxString);
 			}
-		},
-		othChange() {
-			// 鍙嶈В鏋�
-			let ins = this.cron.second
-			('鍙嶈В鏋� second', ins);
-			if (ins === '*') {
-				this.radioValue = 1;
-			} else if (ins.indexOf('-') > -1) {
-				this.radioValue = 2
-			} else if (ins.indexOf('/') > -1) {
-				this.radioValue = 3
-			} else {
-				this.radioValue = 4
-				this.checkboxList = ins.split(',')
-			}
 		}
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'checkboxString': 'checkboxChange',
@@ -113,15 +97,15 @@
 	computed: {
 		// 璁$畻涓や釜鍛ㄦ湡鍊�
 		cycleTotal: function () {
-			this.cycle01 = this.checkNum(this.cycle01, 0, 59)
-			this.cycle02 = this.checkNum(this.cycle02, 0, 59)
-			return this.cycle01 + '-' + this.cycle02;
+			const cycle01 = this.checkNum(this.cycle01, 0, 58)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
+			return cycle01 + '-' + cycle02;
 		},
 		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
 		averageTotal: function () {
-			this.average01 = this.checkNum(this.average01, 0, 59)
-			this.average02 = this.checkNum(this.average02, 1, 59)
-			return this.average01 + '/' + this.average02;
+			const average01 = this.checkNum(this.average01, 0, 58)
+			const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
+			return average01 + '/' + average02;
 		},
 		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
 		checkboxString: function () {
diff --git a/ruoyi-ui/src/components/Crontab/week.vue b/ruoyi-ui/src/components/Crontab/week.vue
index 5ad949d..1cec700 100644
--- a/ruoyi-ui/src/components/Crontab/week.vue
+++ b/ruoyi-ui/src/components/Crontab/week.vue
@@ -2,7 +2,7 @@
 	<el-form size='small'>
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="1">
-				鍛紝鍏佽鐨勯�氶厤绗, - * / L #]
+				鍛紝鍏佽鐨勯�氶厤绗, - * ? / L #]
 			</el-radio>
 		</el-form-item>
 
@@ -15,8 +15,25 @@
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="3">
 				鍛ㄦ湡浠庢槦鏈�
-				<el-input-number v-model='cycle01' :min="1" :max="7" /> -
-				<el-input-number v-model='cycle02' :min="1" :max="7" />
+				<el-select clearable v-model="cycle01">
+					<el-option
+						v-for="(item,index) of weekList"
+						:key="index"
+						:label="item.value"
+						:value="item.key"
+						:disabled="item.key === 1"
+					>{{item.value}}</el-option>
+				</el-select>
+				-
+				<el-select clearable v-model="cycle02">
+					<el-option
+						v-for="(item,index) of weekList"
+						:key="index"
+						:label="item.value"
+						:value="item.key"
+						:disabled="item.key < cycle01 && item.key !== 1"
+					>{{item.value}}</el-option>
+				</el-select>
 			</el-radio>
 		</el-form-item>
 
@@ -24,14 +41,18 @@
 			<el-radio v-model='radioValue' :label="4">
 				绗�
 				<el-input-number v-model='average01' :min="1" :max="4" /> 鍛ㄧ殑鏄熸湡
-				<el-input-number v-model='average02' :min="1" :max="7" />
+				<el-select clearable v-model="average02">
+					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
+				</el-select>
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio v-model='radioValue' :label="5">
 				鏈湀鏈�鍚庝竴涓槦鏈�
-				<el-input-number v-model='weekday' :min="1" :max="7" />
+				<el-select clearable v-model="weekday">
+					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
+				</el-select>
 			</el-radio>
 		</el-form-item>
 
@@ -39,7 +60,7 @@
 			<el-radio v-model='radioValue' :label="6">
 				鎸囧畾
 				<el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%">
-					<el-option v-for="(item,index) of weekList" :key="index" :value="index+1">{{item}}</el-option>
+					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
 				</el-select>
 			</el-radio>
 		</el-form-item>
@@ -52,13 +73,42 @@
 	data() {
 		return {
 			radioValue: 2,
-			weekday: 1,
-			cycle01: 1,
-			cycle02: 2,
+			weekday: 2,
+			cycle01: 2,
+			cycle02: 3,
 			average01: 1,
-			average02: 1,
+			average02: 2,
 			checkboxList: [],
-			weekList: ['鍛ㄤ竴', '鍛ㄤ簩', '鍛ㄤ笁', '鍛ㄥ洓', '鍛ㄤ簲', '鍛ㄥ叚', '鍛ㄦ棩'],
+			weekList: [
+				{
+					key: 2,
+					value: '鏄熸湡涓�'
+				},
+				{
+					key: 3,
+					value: '鏄熸湡浜�'
+				},
+				{
+					key: 4,
+					value: '鏄熸湡涓�'
+				},
+				{
+					key: 5,
+					value: '鏄熸湡鍥�'
+				},
+				{
+					key: 6,
+					value: '鏄熸湡浜�'
+				},
+				{
+					key: 7,
+					value: '鏄熸湡鍏�'
+				},
+				{
+					key: 1,
+					value: '鏄熸湡鏃�'
+				}
+			],
 			checkNum: this.$options.propsData.check
 		}
 	},
@@ -67,45 +117,30 @@
 	methods: {
 		// 鍗曢�夋寜閽�煎彉鍖栨椂
 		radioChange() {
-			if (this.radioValue === 1) {
-				this.$emit('update', 'week', '*');
-				this.$emit('update', 'year', '*');
-			} else {
-				if (this.cron.month === '*') {
-					this.$emit('update', 'month', '0', 'week');
-				}
-				if (this.cron.day === '*') {
-					this.$emit('update', 'day', '0', 'week');
-				}
-				if (this.cron.hour === '*') {
-					this.$emit('update', 'hour', '0', 'week');
-				}
-				if (this.cron.min === '*') {
-					this.$emit('update', 'min', '0', 'week');
-				}
-				if (this.cron.second === '*') {
-					this.$emit('update', 'second', '0', 'week');
-				}
+			if (this.radioValue !== 2 && this.cron.day !== '?') {
+				this.$emit('update', 'day', '?', 'week');
 			}
 			switch (this.radioValue) {
+				case 1:
+					this.$emit('update', 'week', '*');
+					break;
 				case 2:
 					this.$emit('update', 'week', '?');
 					break;
 				case 3:
-					this.$emit('update', 'week', this.cycle01 + '-' + this.cycle02);
+					this.$emit('update', 'week', this.cycleTotal);
 					break;
 				case 4:
-					this.$emit('update', 'week', this.average01 + '#' + this.average02);
+					this.$emit('update', 'week', this.averageTotal);
 					break;
 				case 5:
-					this.$emit('update', 'week', this.weekday + 'L');
+					this.$emit('update', 'week', this.weekdayCheck + 'L');
 					break;
 				case 6:
 					this.$emit('update', 'week', this.checkboxString);
 					break;
 			}
 		},
-		// 鏍规嵁浜掓枼浜嬩欢锛屾洿鏀箁adio鐨勫��
 
 		// 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂
 		cycleChange() {
@@ -133,7 +168,7 @@
 		},
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'weekdayCheck': 'weekdayChange',
@@ -150,7 +185,7 @@
 		averageTotal: function () {
 			this.average01 = this.checkNum(this.average01, 1, 4)
 			this.average02 = this.checkNum(this.average02, 1, 7)
-			return this.average01 + '#' + this.average02;
+			return this.average02 + '#' + this.average01;
 		},
 		// 鏈�杩戠殑宸ヤ綔鏃ワ紙鏍煎紡锛�
 		weekdayCheck: function () {
diff --git a/ruoyi-ui/src/components/Crontab/year.vue b/ruoyi-ui/src/components/Crontab/year.vue
index 800dfa5..5487a6c 100644
--- a/ruoyi-ui/src/components/Crontab/year.vue
+++ b/ruoyi-ui/src/components/Crontab/year.vue
@@ -15,16 +15,16 @@
 		<el-form-item>
 			<el-radio :label="3" v-model='radioValue'>
 				鍛ㄦ湡浠�
-				<el-input-number v-model='cycle01' :min='fullYear' /> -
-				<el-input-number v-model='cycle02' :min='fullYear' />
+				<el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> -
+				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" />
 			</el-radio>
 		</el-form-item>
 
 		<el-form-item>
 			<el-radio :label="4" v-model='radioValue'>
 				浠�
-				<el-input-number v-model='average01' :min='fullYear' /> 骞村紑濮嬶紝姣�
-				<el-input-number v-model='average02' :min='fullYear' /> 骞存墽琛屼竴娆�
+				<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 骞村紑濮嬶紝姣�
+				<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 骞存墽琛屼竴娆�
 			</el-radio>
 
 		</el-form-item>
@@ -59,21 +59,6 @@
 	methods: {
 		// 鍗曢�夋寜閽�煎彉鍖栨椂
 		radioChange() {
-			if (this.cron.month === '*') {
-				this.$emit('update', 'month', '0', 'year');
-			}
-			if (this.cron.day === '*') {
-				this.$emit('update', 'day', '0', 'year');
-			}
-			if (this.cron.hour === '*') {
-				this.$emit('update', 'hour', '0', 'year');
-			}
-			if (this.cron.min === '*') {
-				this.$emit('update', 'min', '0', 'year');
-			}
-			if (this.cron.second === '*') {
-				this.$emit('update', 'second', '0', 'year');
-			}
 			switch (this.radioValue) {
 				case 1:
 					this.$emit('update', 'year', '');
@@ -82,10 +67,10 @@
 					this.$emit('update', 'year', '*');
 					break;
 				case 3:
-					this.$emit('update', 'year', this.cycle01 + '-' + this.cycle02);
+					this.$emit('update', 'year', this.cycleTotal);
 					break;
 				case 4:
-					this.$emit('update', 'year', this.average01 + '/' + this.average02);
+					this.$emit('update', 'year', this.averageTotal);
 					break;
 				case 5:
 					this.$emit('update', 'year', this.checkboxString);
@@ -112,7 +97,7 @@
 		}
 	},
 	watch: {
-		"radioValue": "radioChange",
+		'radioValue': 'radioChange',
 		'cycleTotal': 'cycleChange',
 		'averageTotal': 'averageChange',
 		'checkboxString': 'checkboxChange'
@@ -120,15 +105,15 @@
 	computed: {
 		// 璁$畻涓や釜鍛ㄦ湡鍊�
 		cycleTotal: function () {
-			this.cycle01 = this.checkNum(this.cycle01, this.fullYear, this.fullYear + 100)
-			this.cycle02 = this.checkNum(this.cycle02, this.fullYear + 1, this.fullYear + 101)
-			return this.cycle01 + '-' + this.cycle02;
+			const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
+			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
+			return cycle01 + '-' + cycle02;
 		},
 		// 璁$畻骞冲潎鐢ㄥ埌鐨勫��
 		averageTotal: function () {
-			this.average01 = this.checkNum(this.average01, this.fullYear, this.fullYear + 100)
-			this.average02 = this.checkNum(this.average02, 1, 10)
-			return this.average01 + '/' + this.average02;
+			const average01 = this.checkNum(this.average01, this.fullYear, 2098)
+			const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
+			return average01 + '/' + average02;
 		},
 		// 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆�
 		checkboxString: function () {
@@ -139,6 +124,8 @@
 	mounted: function () {
 		// 浠呰幏鍙栧綋鍓嶅勾浠�
 		this.fullYear = Number(new Date().getFullYear());
+		this.cycle01 = this.fullYear
+		this.average01 = this.fullYear
 	}
 }
 </script>
diff --git a/ruoyi-ui/src/components/ImagePreview/index.vue b/ruoyi-ui/src/components/ImagePreview/index.vue
new file mode 100644
index 0000000..44e27aa
--- /dev/null
+++ b/ruoyi-ui/src/components/ImagePreview/index.vue
@@ -0,0 +1,67 @@
+<template>
+    <el-image :src="`${realSrc}`" fit="cover" :style="`width:${realWidth};height:${realHeight};`" :preview-src-list="[`${realSrc}`]">
+        <div slot="error" class="image-slot">
+          <i class="el-icon-picture-outline"></i>
+        </div>
+    </el-image>
+</template>
+
+<script>
+import { isExternal } from '@/utils/validate'
+
+export default {
+    name: 'ImagePreview',
+    props: {
+        src: {
+            type: String,
+            required: true
+        },
+        width: {
+            type: [Number, String],
+            default: ''
+        },
+        height: {
+            type: [Number, String],
+            default: ''
+        }
+    },
+    computed: {
+        realSrc() {
+            if (isExternal(this.src)) {
+                return this.src
+            }
+            return process.env.VUE_APP_BASE_API + this.src
+        },
+        realWidth() {
+            return typeof this.width == 'string' ? this.width : `${this.width}px`
+        },
+        realHeight() {
+            return typeof this.height == 'string' ? this.height : `${this.height}px`
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.el-image {
+    border-radius: 5px;
+    background-color: #ebeef5;
+    box-shadow: 0 0 5px 1px #ccc;
+    ::v-deep .el-image__inner {
+        transition: all 0.3s;
+        cursor: pointer;
+        &:hover {
+            transform: scale(1.2);
+        }
+    }
+    ::v-deep .image-slot {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 100%;
+        height: 100%;
+        color: #909399;
+        font-size: 30px;
+    }
+}
+</style>
diff --git a/ruoyi-ui/src/directive/index.js b/ruoyi-ui/src/directive/index.js
index 5801640..b9b07da 100644
--- a/ruoyi-ui/src/directive/index.js
+++ b/ruoyi-ui/src/directive/index.js
@@ -3,10 +3,12 @@
 import dialogDrag from './dialog/drag'
 import dialogDragWidth from './dialog/dragWidth'
 import dialogDragHeight from './dialog/dragHeight'
+import clipboard from './module/clipboard'
 
 const install = function(Vue) {
   Vue.directive('hasRole', hasRole)
   Vue.directive('hasPermi', hasPermi)
+  Vue.directive('clipboard', clipboard)
   Vue.directive('dialogDrag', dialogDrag)
   Vue.directive('dialogDragWidth', dialogDragWidth)
   Vue.directive('dialogDragHeight', dialogDragHeight)
diff --git a/ruoyi-ui/src/directive/module/clipboard.js b/ruoyi-ui/src/directive/module/clipboard.js
new file mode 100644
index 0000000..635315a
--- /dev/null
+++ b/ruoyi-ui/src/directive/module/clipboard.js
@@ -0,0 +1,54 @@
+/**
+* v-clipboard 鏂囧瓧澶嶅埗鍓创
+* Copyright (c) 2021 ruoyi
+*/
+
+import Clipboard from 'clipboard'
+export default {
+  bind(el, binding, vnode) {
+    switch (binding.arg) {
+      case 'success':
+        el._vClipBoard_success = binding.value;
+        break;
+      case 'error':
+        el._vClipBoard_error = binding.value;
+        break;
+      default: {
+        const clipboard = new Clipboard(el, {
+          text: () => binding.value,
+          action: () => binding.arg === 'cut' ? 'cut' : 'copy'
+        });
+        clipboard.on('success', e => {
+          const callback = el._vClipBoard_success;
+          callback && callback(e);
+        });
+        clipboard.on('error', e => {
+          const callback = el._vClipBoard_error;
+          callback && callback(e);
+        });
+        el._vClipBoard = clipboard;
+      }
+    }
+  },
+  update(el, binding) {
+    if (binding.arg === 'success') {
+      el._vClipBoard_success = binding.value;
+    } else if (binding.arg === 'error') {
+      el._vClipBoard_error = binding.value;
+    } else {
+      el._vClipBoard.text = function () { return binding.value; };
+      el._vClipBoard.action = () => binding.arg === 'cut' ? 'cut' : 'copy';
+    }
+  },
+  unbind(el, binding) {
+    if (!el._vClipboard) return
+    if (binding.arg === 'success') {
+      delete el._vClipBoard_success;
+    } else if (binding.arg === 'error') {
+      delete el._vClipBoard_error;
+    } else {
+      el._vClipBoard.destroy();
+      delete el._vClipBoard;
+    }
+  }
+}
diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js
index 29c4022..13c6cf2 100644
--- a/ruoyi-ui/src/main.js
+++ b/ruoyi-ui/src/main.js
@@ -29,6 +29,8 @@
 import FileUpload from "@/components/FileUpload"
 // 鍥剧墖涓婁紶缁勪欢
 import ImageUpload from "@/components/ImageUpload"
+// 鍥剧墖棰勮缁勪欢
+import ImagePreview from "@/components/ImagePreview"
 // 瀛楀吀鏍囩缁勪欢
 import DictTag from '@/components/DictTag'
 // 澶撮儴鏍囩缁勪欢
@@ -54,6 +56,7 @@
 Vue.component('Editor', Editor)
 Vue.component('FileUpload', FileUpload)
 Vue.component('ImageUpload', ImageUpload)
+Vue.component('ImagePreview', ImagePreview)
 
 Vue.use(directive)
 Vue.use(plugins)
diff --git a/ruoyi-ui/src/plugins/download.js b/ruoyi-ui/src/plugins/download.js
index ac50dad..726ef54 100644
--- a/ruoyi-ui/src/plugins/download.js
+++ b/ruoyi-ui/src/plugins/download.js
@@ -1,14 +1,17 @@
 import axios from 'axios'
-import { Message } from 'element-ui'
+import {Loading, Message} from 'element-ui'
 import { saveAs } from 'file-saver'
 import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
 import { blobValidate } from "@/utils/ruoyi";
 
 const baseURL = process.env.VUE_APP_BASE_API
+let downloadLoadingInstance;
 
 export default {
   oss(ossId) {
     var url = baseURL + '/system/oss/download/' + ossId
+    downloadLoadingInstance = Loading.service({ text: "姝e湪涓嬭浇鏁版嵁锛岃绋嶅��", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
     axios({
       method: 'get',
       url: url,
@@ -20,8 +23,13 @@
         const blob = new Blob([res.data], { type: 'application/octet-stream' })
         this.saveAs(blob, decodeURI(res.headers['download-filename']))
       } else {
-        Message.error('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�');
+        this.printErrMsg(res.data);
       }
+      downloadLoadingInstance.close();
+    }).catch((r) => {
+      console.error(r)
+      Message.error('涓嬭浇鏂囦欢鍑虹幇閿欒锛岃鑱旂郴绠$悊鍛橈紒')
+      downloadLoadingInstance.close();
     })
   },
   zip(url, name) {
@@ -37,12 +45,18 @@
         const blob = new Blob([res.data], { type: 'application/zip' })
         this.saveAs(blob, name)
       } else {
-        Message.error('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�');
+        this.printErrMsg(res.data);
       }
     })
   },
   saveAs(text, name, opts) {
     saveAs(text, name, opts);
+  },
+  async printErrMsg(data) {
+    const resText = await data.text();
+    const rspObj = JSON.parse(resText);
+    const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+    Message.error(errMsg);
   }
 }
 
diff --git a/ruoyi-ui/src/plugins/modal.js b/ruoyi-ui/src/plugins/modal.js
index 7df61a8..503a16f 100644
--- a/ruoyi-ui/src/plugins/modal.js
+++ b/ruoyi-ui/src/plugins/modal.js
@@ -59,6 +59,14 @@
       type: "warning",
     })
   },
+  // 鎻愪氦鍐呭
+  prompt(content) {
+    return MessageBox.prompt(content, "绯荤粺鎻愮ず", {
+      confirmButtonText: '纭畾',
+      cancelButtonText: '鍙栨秷',
+      type: "warning",
+    })
+  },
   // 鎵撳紑閬僵灞�
   loading(content) {
     loadingInstance = Loading.service({
diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js
index cda6d4c..3fb685d 100644
--- a/ruoyi-ui/src/router/index.js
+++ b/ruoyi-ui/src/router/index.js
@@ -17,6 +17,8 @@
  * redirect: noRedirect             // 褰撹缃� noRedirect 鐨勬椂鍊欒璺敱鍦ㄩ潰鍖呭睉瀵艰埅涓笉鍙鐐瑰嚮
  * name:'router-name'               // 璁惧畾璺敱鐨勫悕瀛楋紝涓�瀹氳濉啓涓嶇劧浣跨敤<keep-alive>鏃朵細鍑虹幇鍚勭闂
  * query: '{"id": 1, "name": "ry"}' // 璁块棶璺敱鐨勯粯璁や紶閫掑弬鏁�
+ * roles: ['admin', 'common']       // 璁块棶璺敱鐨勮鑹叉潈闄�
+ * permissions: ['a:a:a', 'b:b:b']  // 璁块棶璺敱鐨勮彍鍗曟潈闄�
  * meta : {
     noCache: true                   // 濡傛灉璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive> 缂撳瓨(榛樿 false)
     title: 'title'                  // 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
@@ -35,28 +37,28 @@
     children: [
       {
         path: '/redirect/:path(.*)',
-        component: (resolve) => require(['@/views/redirect'], resolve)
+        component: () => import('@/views/redirect')
       }
     ]
   },
   {
     path: '/login',
-    component: (resolve) => require(['@/views/login'], resolve),
+    component: () => import('@/views/login'),
     hidden: true
   },
   {
     path: '/register',
-    component: (resolve) => require(['@/views/register'], resolve),
+    component: () => import('@/views/register'),
     hidden: true
   },
   {
     path: '/404',
-    component: (resolve) => require(['@/views/error/404'], resolve),
+    component: () => import('@/views/error/404'),
     hidden: true
   },
   {
     path: '/401',
-    component: (resolve) => require(['@/views/error/401'], resolve),
+    component: () => import('@/views/error/401'),
     hidden: true
   },
   {
@@ -66,7 +68,7 @@
     children: [
       {
         path: 'index',
-        component: (resolve) => require(['@/views/index'], resolve),
+        component: () => import('@/views/index'),
         name: 'Index',
         meta: { title: '棣栭〉', icon: 'dashboard', affix: true }
       }
@@ -80,20 +82,25 @@
     children: [
       {
         path: 'profile',
-        component: (resolve) => require(['@/views/system/user/profile/index'], resolve),
+        component: () => import('@/views/system/user/profile/index'),
         name: 'Profile',
         meta: { title: '涓汉涓績', icon: 'user' }
       }
     ]
-  },
+  }
+]
+
+// 鍔ㄦ�佽矾鐢憋紝鍩轰簬鐢ㄦ埛鏉冮檺鍔ㄦ�佸幓鍔犺浇
+export const dynamicRoutes = [
   {
     path: '/system/user-auth',
     component: Layout,
     hidden: true,
+    permissions: ['system:user:edit'],
     children: [
       {
         path: 'role/:userId(\\d+)',
-        component: (resolve) => require(['@/views/system/user/authRole'], resolve),
+        component: () => import('@/views/system/user/authRole'),
         name: 'AuthRole',
         meta: { title: '鍒嗛厤瑙掕壊', activeMenu: '/system/user' }
       }
@@ -103,10 +110,11 @@
     path: '/system/role-auth',
     component: Layout,
     hidden: true,
+    permissions: ['system:role:edit'],
     children: [
       {
         path: 'user/:roleId(\\d+)',
-        component: (resolve) => require(['@/views/system/role/authUser'], resolve),
+        component: () => import('@/views/system/role/authUser'),
         name: 'AuthUser',
         meta: { title: '鍒嗛厤鐢ㄦ埛', activeMenu: '/system/role' }
       }
@@ -116,10 +124,11 @@
     path: '/system/dict-data',
     component: Layout,
     hidden: true,
+    permissions: ['system:dict:list'],
     children: [
       {
         path: 'index/:dictId(\\d+)',
-        component: (resolve) => require(['@/views/system/dict/data'], resolve),
+        component: () => import('@/views/system/dict/data'),
         name: 'Data',
         meta: { title: '瀛楀吀鏁版嵁', activeMenu: '/system/dict' }
       }
@@ -129,12 +138,13 @@
     path: '/system/oss-config',
     component: Layout,
     hidden: true,
+    permissions: ['system:oss:list'],
     children: [
       {
         path: 'index',
-        component: (resolve) => require(['@/views/system/oss/config'], resolve),
+        component: () => import('@/views/system/oss/config'),
         name: 'OssConfig',
-        meta: { title: '閰嶇疆绠$悊', activeMenu: '/system/oss'}
+        meta: { title: '閰嶇疆绠$悊', activeMenu: '/system/oss' }
       }
     ]
   },
@@ -142,10 +152,11 @@
     path: '/tool/gen-edit',
     component: Layout,
     hidden: true,
+    permissions: ['tool:gen:edit'],
     children: [
       {
         path: 'index',
-        component: (resolve) => require(['@/views/tool/gen/editTable'], resolve),
+        component: () => import('@/views/tool/gen/editTable'),
         name: 'GenEdit',
         meta: { title: '淇敼鐢熸垚閰嶇疆', activeMenu: '/tool/gen' }
       }
diff --git a/ruoyi-ui/src/store/modules/permission.js b/ruoyi-ui/src/store/modules/permission.js
index 8d84fff..6f08c6f 100644
--- a/ruoyi-ui/src/store/modules/permission.js
+++ b/ruoyi-ui/src/store/modules/permission.js
@@ -1,4 +1,5 @@
-import { constantRoutes } from '@/router'
+import auth from '@/plugins/auth'
+import router, { constantRoutes, dynamicRoutes } from '@/router'
 import { getRouters } from '@/api/menu'
 import Layout from '@/layout/index'
 import ParentView from '@/components/ParentView'
@@ -42,7 +43,9 @@
           const rdata = JSON.parse(JSON.stringify(res.data))
           const sidebarRoutes = filterAsyncRouter(sdata)
           const rewriteRoutes = filterAsyncRouter(rdata, false, true)
+          const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
           rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
+          router.addRoutes(asyncRoutes);
           commit('SET_ROUTES', rewriteRoutes)
           commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
           commit('SET_DEFAULT_ROUTES', sidebarRoutes)
@@ -106,6 +109,23 @@
   return children
 }
 
+// 鍔ㄦ�佽矾鐢遍亶鍘嗭紝楠岃瘉鏄惁鍏峰鏉冮檺
+export function filterDynamicRoutes(routes) {
+  const res = []
+  routes.forEach(route => {
+    if (route.permissions) {
+      if (auth.hasPermiOr(route.permissions)) {
+        res.push(route)
+      }
+    } else if (route.roles) {
+      if (auth.hasRoleOr(route.roles)) {
+        res.push(route)
+      }
+    }
+  })
+  return res
+}
+
 export const loadView = (view) => {
   if (process.env.NODE_ENV === 'development') {
     return (resolve) => require([`@/views/${view}`], resolve)
diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js
index d376a76..a391757 100644
--- a/ruoyi-ui/src/utils/request.js
+++ b/ruoyi-ui/src/utils/request.js
@@ -110,7 +110,10 @@
       const blob = new Blob([data])
       saveAs(blob, filename)
     } else {
-      Message.error('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�');
+      const resText = await data.text();
+      const rspObj = JSON.parse(resText);
+      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+      Message.error(errMsg);
     }
     downloadLoadingInstance.close();
   }).catch((r) => {
diff --git a/ruoyi-ui/src/views/monitor/online/index.vue b/ruoyi-ui/src/views/monitor/online/index.vue
index 509fbe5..dba6e06 100644
--- a/ruoyi-ui/src/views/monitor/online/index.vue
+++ b/ruoyi-ui/src/views/monitor/online/index.vue
@@ -111,7 +111,7 @@
     },
     /** 寮洪��鎸夐挳鎿嶄綔 */
     handleForceLogout(row) {
-      this.$modal.confirm('鏄惁纭寮洪��鍚嶇О涓�"' + row.userName + '"鐨勬暟鎹」锛�').then(function() {
+      this.$modal.confirm('鏄惁纭寮洪��鍚嶇О涓�"' + row.userName + '"鐨勭敤鎴凤紵').then(function() {
         return forceLogout(row.tokenId);
       }).then(() => {
         this.getList();
diff --git a/ruoyi-ui/src/views/system/menu/index.vue b/ruoyi-ui/src/views/system/menu/index.vue
index d65773a..5c1f85a 100644
--- a/ruoyi-ui/src/views/system/menu/index.vue
+++ b/ruoyi-ui/src/views/system/menu/index.vue
@@ -128,7 +128,7 @@
             </el-form-item>
           </el-col>
           <el-col :span="24" v-if="form.menuType != 'F'">
-            <el-form-item label="鑿滃崟鍥炬爣">
+            <el-form-item label="鑿滃崟鍥炬爣" prop="icon">
               <el-popover
                 placement="bottom-start"
                 width="460"
diff --git a/ruoyi-ui/src/views/system/user/authRole.vue b/ruoyi-ui/src/views/system/user/authRole.vue
index 52a7923..7abe26a 100644
--- a/ruoyi-ui/src/views/system/user/authRole.vue
+++ b/ruoyi-ui/src/views/system/user/authRole.vue
@@ -9,7 +9,7 @@
           </el-form-item>
         </el-col>
         <el-col :span="8" :offset="2">
-          <el-form-item label="鐧诲綍璐﹀彿" prop="phonenumber">
+          <el-form-item label="鐧诲綍璐﹀彿" prop="userName">
             <el-input  v-model="form.userName" disabled />
           </el-form-item>
         </el-col>
diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue
index 1ff9b90..0eb8ddc 100644
--- a/ruoyi-ui/src/views/system/user/index.vue
+++ b/ruoyi-ui/src/views/system/user/index.vue
@@ -596,7 +596,7 @@
         cancelButtonText: "鍙栨秷",
         closeOnClickModal: false,
         inputPattern: /^.{5,20}$/,
-        inputErrorMessage: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿",
+        inputErrorMessage: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿"
       }).then(({ value }) => {
           resetUserPwd(row.userId, value).then(response => {
             this.$modal.msgSuccess("淇敼鎴愬姛锛屾柊瀵嗙爜鏄細" + value);
@@ -663,7 +663,7 @@
       this.upload.open = false;
       this.upload.isUploading = false;
       this.$refs.upload.clearFiles();
-      this.$alert(response.msg, "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true });
+      this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true });
       this.getList();
     },
     // 鎻愪氦涓婁紶鏂囦欢
diff --git a/ruoyi-ui/src/views/tool/gen/basicInfoForm.vue b/ruoyi-ui/src/views/tool/gen/basicInfoForm.vue
index 757962c..7029529 100644
--- a/ruoyi-ui/src/views/tool/gen/basicInfoForm.vue
+++ b/ruoyi-ui/src/views/tool/gen/basicInfoForm.vue
@@ -11,7 +11,6 @@
           <el-input placeholder="璇疯緭鍏�" v-model="info.tableComment" />
         </el-form-item>
       </el-col>
-
       <el-col :span="12">
         <el-form-item label="瀹炰綋绫诲悕绉�" prop="className">
           <el-input placeholder="璇疯緭鍏�" v-model="info.className" />
@@ -30,9 +29,9 @@
     </el-row>
   </el-form>
 </template>
+
 <script>
 export default {
-  name: "BasicInfoForm",
   props: {
     info: {
       type: Object,
diff --git a/ruoyi-ui/src/views/tool/gen/editTable.vue b/ruoyi-ui/src/views/tool/gen/editTable.vue
index 6ba7f5d..2141772 100644
--- a/ruoyi-ui/src/views/tool/gen/editTable.vue
+++ b/ruoyi-ui/src/views/tool/gen/editTable.vue
@@ -124,6 +124,7 @@
     </el-form>
   </el-card>
 </template>
+
 <script>
 import { getGenTable, updateGenTable } from "@/api/tool/gen";
 import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
diff --git a/ruoyi-ui/src/views/tool/gen/genInfoForm.vue b/ruoyi-ui/src/views/tool/gen/genInfoForm.vue
index f227156..0a1de16 100644
--- a/ruoyi-ui/src/views/tool/gen/genInfoForm.vue
+++ b/ruoyi-ui/src/views/tool/gen/genInfoForm.vue
@@ -11,7 +11,6 @@
           </el-select>
         </el-form-item>
       </el-col>
-
       <el-col :span="12">
         <el-form-item prop="packageName">
           <span slot="label">
@@ -213,12 +212,12 @@
     </el-row>
   </el-form>
 </template>
+
 <script>
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 
 export default {
-  name: "BasicInfoForm",
   components: { Treeselect },
   props: {
     info: {
diff --git a/ruoyi-ui/src/views/tool/gen/index.vue b/ruoyi-ui/src/views/tool/gen/index.vue
index 646decf..3b7c902 100644
--- a/ruoyi-ui/src/views/tool/gen/index.vue
+++ b/ruoyi-ui/src/views/tool/gen/index.vue
@@ -169,7 +169,8 @@
           :name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))"
           :key="key"
         >
-        <pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre>
+          <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="value" v-clipboard:success="clipboardSuccess" style="float:right">澶嶅埗</el-link>
+          <pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre>
         </el-tab-pane>
       </el-tabs>
     </el-dialog>
@@ -306,6 +307,10 @@
       const result = hljs.highlight(language, code || "", true);
       return result.value || '&nbsp;';
     },
+    /** 澶嶅埗浠g爜鎴愬姛 */
+    clipboardSuccess(){
+      this.$modal.msgSuccess("澶嶅埗鎴愬姛");
+    },
     // 澶氶�夋閫変腑鏁版嵁
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.tableId);
diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js
index 73c2177..a96dff0 100644
--- a/ruoyi-ui/vue.config.js
+++ b/ruoyi-ui/vue.config.js
@@ -5,6 +5,8 @@
   return path.join(__dirname, dir)
 }
 
+const CompressionPlugin = require('compression-webpack-plugin')
+
 const name = process.env.VUE_APP_TITLE || 'RuoYi-Vue-Plus鍚庡彴绠$悊绯荤粺' // 缃戦〉鏍囬
 
 const port = process.env.port || process.env.npm_config_port || 80 // 绔彛
@@ -42,13 +44,29 @@
     },
     disableHostCheck: true
   },
+  css: {
+    loaderOptions: {
+      sass: {
+        sassOptions: { outputStyle: "expanded" }
+      }
+    }
+  },
   configureWebpack: {
     name: name,
     resolve: {
       alias: {
         '@': resolve('src')
       }
-    }
+    },
+    plugins: [
+      // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#浣跨敤gzip瑙e帇缂╅潤鎬佹枃浠�
+      new CompressionPlugin({
+        test: /\.(js|css|html)?$/i,     // 鍘嬬缉鏂囦欢鏍煎紡
+        filename: '[path].gz[query]',   // 鍘嬬缉鍚庣殑鏂囦欢鍚�
+        algorithm: 'gzip',              // 浣跨敤gzip鍘嬬缉
+        minRatio: 0.8                   // 鍘嬬缉鐜囧皬浜�1鎵嶄細鍘嬬缉
+      })
+    ],
   },
   chainWebpack(config) {
     config.plugins.delete('preload') // TODO: need test
diff --git a/script/docker/nginx/nginx.conf b/script/docker/nginx/nginx.conf
index b4ba031..e77b6c7 100644
--- a/script/docker/nginx/nginx.conf
+++ b/script/docker/nginx/nginx.conf
@@ -52,6 +52,16 @@
         #ssl_prefer_server_ciphers on;
         # https閰嶇疆鍙傝�� end
 
+        # 婕旂ず鐜閰嶇疆 鎷︽埅闄� GET POST 涔嬪鐨勬墍鏈夎姹�
+        # if ($request_method !~* GET|POST) {
+        #     rewrite  ^/(.*)$  /403;
+        # }
+
+        # location = /403 {
+        #     default_type application/json;
+        #     return 200 '{"msg":"婕旂ず妯″紡锛屼笉鍏佽鎿嶄綔","code":500}';
+        # }
+
 		location / {
             root   /usr/share/nginx/html;
 			try_files $uri $uri/ /index.html;
@@ -66,6 +76,9 @@
 			proxy_pass http://server/;
 		}
 
+        # https 浼氭嫤鎴唴閾炬墍鏈夌殑 http 璇锋眰 閫犳垚鍔熻兘鏃犳硶浣跨敤
+        # 瑙e喅鏂规1 灏� admin 鏈嶅姟 涔熼厤缃垚 https
+        # 瑙e喅鏂规2 灏嗚彍鍗曢厤缃负澶栭摼璁块棶 璧扮嫭绔嬮〉闈� http 璁块棶
 		location /admin/ {
 			proxy_set_header Host $http_host;
 			proxy_set_header X-Real-IP $remote_addr;
@@ -74,6 +87,9 @@
 			proxy_pass http://monitor-admin/admin/;
 		}
 
+        # https 浼氭嫤鎴唴閾炬墍鏈夌殑 http 璇锋眰 閫犳垚鍔熻兘鏃犳硶浣跨敤
+        # 瑙e喅鏂规1 灏� xxljob 鏈嶅姟 涔熼厤缃垚 https
+        # 瑙e喅鏂规2 灏嗚彍鍗曢厤缃负澶栭摼璁块棶 璧扮嫭绔嬮〉闈� http 璁块棶
         location /xxl-job-admin/ {
             proxy_set_header Host $http_host;
             proxy_set_header X-Real-IP $remote_addr;
diff --git a/script/docker/redis/redis.conf b/script/docker/redis/redis.conf
index 7d550e1..a07c9d2 100644
--- a/script/docker/redis/redis.conf
+++ b/script/docker/redis/redis.conf
@@ -1,6 +1,9 @@
 # redis 瀵嗙爜
 # requirepass ruoyi123
 
+# key 鐩戝惉鍣ㄩ厤缃�
+# notify-keyspace-events Ex
+
 # 閰嶇疆鎸佷箙鍖栨枃浠跺瓨鍌ㄨ矾寰�
 dir /redis/data
 # 閰嶇疆rdb

--
Gitblit v1.9.3