Pārlūkot izejas kodu

Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/activiti

 Conflicts:
	sql/ruoyi-vue-pro.sql
	yudao-admin-server/src/main/resources/application.yaml
	yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml
	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java
	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
YunaiV 3 gadi atpakaļ
vecāks
revīzija
4b2af44ee3
100 mainītis faili ar 1812 papildinājumiem un 383 dzēšanām
  1. 9 8
      README.md
  2. BIN
      img.png
  3. 3 3
      pom.xml
  4. 45 42
      sql/ruoyi-vue-pro.sql
  5. 8 2
      yudao-admin-server/pom.xml
  6. 0 9
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/config/AsyncConfiguration.java
  7. 0 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/package-info.java
  8. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java
  9. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java
  10. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java
  11. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java
  12. 5 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http
  13. 4 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
  14. 106 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java
  15. 30 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java
  16. 14 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java
  17. 39 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java
  18. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java
  19. 41 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java
  20. 19 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java
  21. 18 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java
  22. 2 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http
  23. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java
  24. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java
  25. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java
  26. 2 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java
  27. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysOperateLogDO.java
  28. 3 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java
  29. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java
  30. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysMenuMapper.java
  31. 44 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java
  32. 3 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
  33. 7 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaProperties.java
  34. 25 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java
  35. 4 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java
  36. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/auth/SysUserSessionTimeoutJob.java
  37. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java
  38. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java
  39. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java
  40. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java
  41. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java
  42. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java
  43. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java
  44. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java
  45. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java
  46. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java
  47. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java
  48. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java
  49. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java
  50. 4 7
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java
  51. 42 42
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
  52. 7 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java
  53. 5 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java
  54. 8 12
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysDeptServiceImpl.java
  55. 2 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java
  56. 70 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java
  57. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysRoleServiceImpl.java
  58. 83 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java
  59. 91 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java
  60. 5 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenEngine.java
  61. 11 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenSQLParser.java
  62. 1 0
      yudao-admin-server/src/main/resources/application-dev.yaml
  63. 3 0
      yudao-admin-server/src/main/resources/application-local.yaml
  64. 3 1
      yudao-admin-server/src/main/resources/application.yaml
  65. 5 5
      yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm
  66. 1 1
      yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml
  67. 8 8
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigServiceTest.java
  68. 5 5
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java
  69. 11 11
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogServiceTest.java
  70. 7 7
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobServiceTest.java
  71. 14 14
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java
  72. 17 18
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java
  73. 11 3
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java
  74. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java
  75. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java
  76. 4 4
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java
  77. 6 9
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataServiceTest.java
  78. 8 8
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeServiceTest.java
  79. 5 5
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeServiceTest.java
  80. 8 8
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java
  81. 10 10
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogServiceImplTest.java
  82. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java
  83. 121 1
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java
  84. 4 4
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleServiceTest.java
  85. 3 3
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelServiceTest.java
  86. 14 14
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogServiceTest.java
  87. 14 14
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateServiceTest.java
  88. 181 0
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java
  89. 5 5
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java
  90. 1 0
      yudao-admin-server/src/test/resources/sql/clean.sql
  91. 26 3
      yudao-admin-server/src/test/resources/sql/create_tables.sql
  92. 65 0
      yudao-admin-ui/src/api/system/tenant.js
  93. 6 0
      yudao-admin-ui/src/utils/request.js
  94. 35 3
      yudao-admin-ui/src/views/login.vue
  95. 259 0
      yudao-admin-ui/src/views/system/tenant/index.vue
  96. 9 6
      yudao-core-service/pom.xml
  97. 2 1
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java
  98. 2 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java
  99. 3 3
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java
  100. 16 0
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/file/InfFileCoreMapper.java

+ 9 - 8
README.md

@@ -33,6 +33,7 @@
 |  | 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等 |
 |  | 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等 |
 |  | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
 |  | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
 |  | 岗位管理 | 配置系统用户所属担任职务 |
 |  | 岗位管理 | 配置系统用户所属担任职务 |
+|  | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
 |  | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
 |  | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
 | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 |
 | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 |
 | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
 | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
@@ -96,21 +97,21 @@
 
 
 | 框架 | 说明 |  版本 | 学习指南 |
 | 框架 | 说明 |  版本 | 学习指南 |
 | --- | --- | --- | --- |
 | --- | --- | --- | --- |
-| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.5 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
+| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.12 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
 | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 |  |
 | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 |  |
-| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.4 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
-| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
-| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
+| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.8 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
+| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.3.4 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
+| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
 | [Redis](https://redis.io/) | key-value 数据库 | 5.0 |  |
 | [Redis](https://redis.io/) | key-value 数据库 | 5.0 |  |
-| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.1.46 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
-| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架  | 5.4.6 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
-| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.4.6 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
+| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.16.6 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
+| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架  | 5.3.13 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
+| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.4.9 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
 | [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.1.7 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
 | [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.1.7 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
 | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
 | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
 | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
 | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
 | [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
 | [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
 | [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
 | [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
-| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
+| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.4.2 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
 | [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.11.4 |  |
 | [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.11.4 |  |
 | [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
 | [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
 | [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
 | [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |

BIN
img.png


+ 3 - 3
pom.xml

@@ -20,7 +20,7 @@
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
 
     <properties>
     <properties>
-        <revision>1.2.0-snapshot</revision>
+        <revision>1.3.0-snapshot</revision>
         <!-- Maven 相关 -->
         <!-- Maven 相关 -->
         <java.version>1.8</java.version>
         <java.version>1.8</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>
         <maven.compiler.source>${java.version}</maven.compiler.source>
@@ -58,9 +58,9 @@
     <!-- 使用 aliyun 的 Maven 源,提升下载速度 -->
     <!-- 使用 aliyun 的 Maven 源,提升下载速度 -->
     <repositories>
     <repositories>
         <repository>
         <repository>
-            <id>aliyun</id>
+            <id>aliyunmaven</id>
             <name>aliyun</name>
             <name>aliyun</name>
-            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
+            <url>https://maven.aliyun.com/repository/public</url>
         </repository>
         </repository>
     </repositories>
     </repositories>
 
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 45 - 42
sql/ruoyi-vue-pro.sql


+ 8 - 2
yudao-admin-server/pom.xml

@@ -35,6 +35,14 @@
             <groupId>cn.iocoder.boot</groupId>
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
             <artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
+        </dependency>
 
 
         <dependency>
         <dependency>
             <groupId>cn.iocoder.boot</groupId>
             <groupId>cn.iocoder.boot</groupId>
@@ -117,8 +125,6 @@
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
         </dependency>
         </dependency>
 
 
-
-
         <dependency>
         <dependency>
             <groupId>org.apache.velocity</groupId>
             <groupId>org.apache.velocity</groupId>
             <artifactId>velocity-engine-core</artifactId>
             <artifactId>velocity-engine-core</artifactId>

+ 0 - 9
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/config/AsyncConfiguration.java

@@ -1,9 +0,0 @@
-package cn.iocoder.yudao.adminserver.framework.async.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableAsync;
-
-@Configuration
-@EnableAsync
-public class AsyncConfiguration {
-}

+ 0 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/package-info.java

@@ -1,4 +0,0 @@
-/**
- * 异步执行,基于 Spring @Async 实现
- */
-package cn.iocoder.yudao.adminserver.framework.async;

+ 4 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java

@@ -22,9 +22,11 @@ public class SecurityConfiguration {
     @Bean
     @Bean
     public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
     public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
         return registry -> {
         return registry -> {
-            // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
+            // 验证码的接口
             registry.antMatchers(api("/system/captcha/**")).anonymous();
             registry.antMatchers(api("/system/captcha/**")).anonymous();
-            // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
+            // 获得租户编号的接口
+            registry.antMatchers(api("/system/tenant/get-id-by-name")).anonymous();
+            // Spring Boot Admin Server 的安全配置
             registry.antMatchers(adminSeverContextPath).anonymous()
             registry.antMatchers(adminSeverContextPath).anonymous()
                     .antMatchers(adminSeverContextPath + "/**").anonymous();
                     .antMatchers(adminSeverContextPath + "/**").anonymous();
             // 短信回调 API
             // 短信回调 API

+ 2 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert;
 import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiImplicitParams;
@@ -64,6 +65,7 @@ public class InfFileController {
     @ApiOperation("下载文件")
     @ApiOperation("下载文件")
     @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
     @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
     public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
     public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
+        TenantContextHolder.setNullTenantId();
         InfFileDO file = fileCoreService.getFile(path);
         InfFileDO file = fileCoreService.getFile(path);
         if (file == null) {
         if (file == null) {
             log.warn("[getFile][path({}) 文件不存在]", path);
             log.warn("[getFile][path({}) 文件不存在]", path);

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java

@@ -1,13 +1,13 @@
 package cn.iocoder.yudao.adminserver.modules.infra.mq.message.config;
 package cn.iocoder.yudao.adminserver.modules.infra.mq.message.config;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
 
 
 /**
 /**
  * 配置数据刷新 Message
  * 配置数据刷新 Message
  */
  */
 @Data
 @Data
-public class InfConfigRefreshMessage implements ChannelMessage {
+public class InfConfigRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config;
 package cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config;
 
 
 import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage;
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
 public class InfConfigProducer {
 public class InfConfigProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link InfConfigRefreshMessage} 消息
      * 发送 {@link InfConfigRefreshMessage} 消息
      */
      */
     public void sendConfigRefreshMessage() {
     public void sendConfigRefreshMessage() {
         InfConfigRefreshMessage message = new InfConfigRefreshMessage();
         InfConfigRefreshMessage message = new InfConfigRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 5 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http

@@ -1,21 +1,25 @@
 ### 请求 /login 接口 => 成功
 ### 请求 /login 接口 => 成功
 POST {{baseUrl}}/login
 POST {{baseUrl}}/login
 Content-Type: application/json
 Content-Type: application/json
+tenant-id: 1
 
 
 {
 {
   "username": "admin",
   "username": "admin",
   "password": "admin123",
   "password": "admin123",
-  "uuid": "9b2ffbc1-7425-4155-9894-9d5c08541d62",
+  "uuid": "3acd87a09a4f48fb9118333780e94883",
   "code": "1024"
   "code": "1024"
 }
 }
 
 
 ### 请求 /get-permission-info 接口 => 成功
 ### 请求 /get-permission-info 接口 => 成功
 GET {{baseUrl}}/get-permission-info
 GET {{baseUrl}}/get-permission-info
 Authorization: Bearer {{token}}
 Authorization: Bearer {{token}}
+tenant-id: 1
 
 
 ### 请求 /list-menus 接口 => 成功
 ### 请求 /list-menus 接口 => 成功
 GET {{baseUrl}}/list-menus
 GET {{baseUrl}}/list-menus
 Authorization: Bearer {{token}}
 Authorization: Bearer {{token}}
+#Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a
+tenant-id: 1
 
 
 ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
 ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
 GET http://127.0.0.1:8080/druid/123
 GET http://127.0.0.1:8080/druid/123

+ 4 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -50,7 +50,7 @@ public class SysAuthController {
     @Resource
     @Resource
     private SysPermissionService permissionService;
     private SysPermissionService permissionService;
     @Resource
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialCoreService;
 
 
     @PostMapping("/login")
     @PostMapping("/login")
     @ApiOperation("使用账号密码登录")
     @ApiOperation("使用账号密码登录")
@@ -102,7 +102,7 @@ public class SysAuthController {
     })
     })
     public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
     public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
                                                     @RequestParam("redirectUri") String redirectUri) {
                                                     @RequestParam("redirectUri") String redirectUri) {
-        return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
+        return CommonResult.success(socialCoreService.getAuthorizeUrl(type, redirectUri));
     }
     }
 
 
     @PostMapping("/social-login")
     @PostMapping("/social-login")
@@ -133,7 +133,7 @@ public class SysAuthController {
     @DeleteMapping("/social-unbind")
     @DeleteMapping("/social-unbind")
     @ApiOperation("取消社交绑定")
     @ApiOperation("取消社交绑定")
     public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
     public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
-        socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
+        socialCoreService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
         return CommonResult.success(true);
         return CommonResult.success(true);
     }
     }
 
 

+ 106 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java

@@ -0,0 +1,106 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.*;
+import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
+import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+@Api(tags = "租户")
+@RestController
+@RequestMapping("/system/tenant")
+public class SysTenantController {
+
+    @Resource
+    private SysTenantService tenantService;
+
+    @GetMapping("/get-id-by-name")
+    @ApiOperation(value = "使用租户名,获得租户编号", notes = "登录界面,根据用户的租户名,获得租户编号")
+    @ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class)
+    public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
+        SysTenantDO tenantDO = tenantService.getTenantByName(name);
+        return success(tenantDO != null ? tenantDO.getId() : null);
+    }
+
+    @PostMapping("/create")
+    @ApiOperation("创建租户")
+    @PreAuthorize("@ss.hasPermission('system:tenant:create')")
+    public CommonResult<Long> createTenant(@Valid @RequestBody SysTenantCreateReqVO createReqVO) {
+        return success(tenantService.createTenant(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("更新租户")
+    @PreAuthorize("@ss.hasPermission('system:tenant:update')")
+    public CommonResult<Boolean> updateTenant(@Valid @RequestBody SysTenantUpdateReqVO updateReqVO) {
+        tenantService.updateTenant(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除租户")
+    @ApiImplicitParam(name = "id", value = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('system:tenant:delete')")
+    public CommonResult<Boolean> deleteTenant(@RequestParam("id") Long id) {
+        tenantService.deleteTenant(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得租户")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
+    public CommonResult<SysTenantRespVO> getTenant(@RequestParam("id") Long id) {
+        SysTenantDO tenant = tenantService.getTenant(id);
+        return success(SysTenantConvert.INSTANCE.convert(tenant));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获得租户列表")
+    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
+    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
+    public CommonResult<List<SysTenantRespVO>> getTenantList(@RequestParam("ids") Collection<Long> ids) {
+        List<SysTenantDO> list = tenantService.getTenantList(ids);
+        return success(SysTenantConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得租户分页")
+    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
+    public CommonResult<PageResult<SysTenantRespVO>> getTenantPage(@Valid SysTenantPageReqVO pageVO) {
+        PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(pageVO);
+        return success(SysTenantConvert.INSTANCE.convertPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @ApiOperation("导出租户 Excel")
+    @PreAuthorize("@ss.hasPermission('system:tenant:export')")
+    @OperateLog(type = EXPORT)
+    public void exportTenantExcel(@Valid SysTenantExportReqVO exportReqVO,
+                                  HttpServletResponse response) throws IOException {
+        List<SysTenantDO> list = tenantService.getTenantList(exportReqVO);
+        // 导出 Excel
+        List<SysTenantExcelVO> datas = SysTenantConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "租户.xls", "数据", SysTenantExcelVO.class, datas);
+    }
+
+
+}

+ 30 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+/**
+* 租户 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class SysTenantBaseVO {
+
+    @ApiModelProperty(value = "租户名", required = true, example = "芋道")
+    @NotNull(message = "租户名不能为空")
+    private String name;
+
+    @ApiModelProperty(value = "联系人", required = true, example = "芋艿")
+    @NotNull(message = "联系人不能为空")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系手机", example = "15601691300")
+    private String contactMobile;
+
+    @ApiModelProperty(value = "租户状态(0正常 1停用)", required = true, example = "1")
+    @NotNull(message = "租户状态(0正常 1停用)不能为空")
+    private Integer status;
+
+}

+ 14 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("租户创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantCreateReqVO extends SysTenantBaseVO {
+
+}

+ 39 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+
+/**
+ * 租户 Excel VO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class SysTenantExcelVO {
+
+    @ExcelProperty("租户编号")
+    private Long id;
+
+    @ExcelProperty("租户名")
+    private String name;
+
+    @ExcelProperty("联系人")
+    private String contactName;
+
+    @ExcelProperty("联系手机")
+    private String contactMobile;
+
+    @ExcelProperty(value = "租户状态(0正常 1停用)", converter = DictConvert.class)
+    @DictFormat("sys_common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
+    private Integer status;
+
+    @ExcelProperty("创建时间")
+    private Date createTime;
+
+}

+ 36 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel(value = "租户 Excel 导出 Request VO", description = "参数和 SysTenantPageReqVO 是一致的")
+@Data
+public class SysTenantExportReqVO {
+
+    @ApiModelProperty(value = "租户名", example = "芋道")
+    private String name;
+
+    @ApiModelProperty(value = "联系人", example = "芋艿")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系手机", example = "15601691300")
+    private String contactMobile;
+
+    @ApiModelProperty(value = "租户状态(0正常 1停用)", example = "1")
+    private Integer status;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 41 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("租户分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantPageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "租户名", example = "芋道")
+    private String name;
+
+    @ApiModelProperty(value = "联系人", example = "芋艿")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系手机", example = "15601691300")
+    private String contactMobile;
+
+    @ApiModelProperty(value = "租户状态(0正常 1停用)", example = "1")
+    private Integer status;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 19 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+@ApiModel("租户 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantRespVO extends SysTenantBaseVO {
+
+    @ApiModelProperty(value = "租户编号", required = true, example = "1024")
+    private Long id;
+
+    @ApiModelProperty(value = "创建时间", required = true)
+    private Date createTime;
+
+}

+ 18 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("租户更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantUpdateReqVO extends SysTenantBaseVO {
+
+    @ApiModelProperty(value = "租户编号", required = true, example = "1024")
+    @NotNull(message = "租户编号不能为空")
+    private Long id;
+
+}

+ 2 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http

@@ -1,3 +1,4 @@
 ### 请求 /system/user/page 接口 => 没有权限
 ### 请求 /system/user/page 接口 => 没有权限
 GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
 GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
-Authorization: Bearer test104 # 使用测试账号
+Authorization: Bearer test1 # 使用测试账号
+tenant-id: 1

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java

@@ -15,7 +15,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleSer
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
@@ -56,7 +56,7 @@ public class SysUserProfileController {
     @Resource
     @Resource
     private SysRoleService roleService;
     private SysRoleService roleService;
     @Resource
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
 
     @GetMapping("/get")
     @GetMapping("/get")
     @ApiOperation("获得登录用户信息")
     @ApiOperation("获得登录用户信息")

+ 36 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.adminserver.modules.system.convert.tenant;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExcelVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantRespVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 租户 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface SysTenantConvert {
+
+    SysTenantConvert INSTANCE = Mappers.getMapper(SysTenantConvert.class);
+
+    SysTenantDO convert(SysTenantCreateReqVO bean);
+
+    SysTenantDO convert(SysTenantUpdateReqVO bean);
+
+    SysTenantRespVO convert(SysTenantDO bean);
+
+    List<SysTenantRespVO> convertList(List<SysTenantDO> list);
+
+    PageResult<SysTenantRespVO> convertPage(PageResult<SysTenantDO> page);
+
+    List<SysTenantExcelVO> convertList02(List<SysTenantDO> list);
+
+}

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
 
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.Data;
@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
 @TableName("sys_dept")
 @TableName("sys_dept")
 @Data
 @Data
 @EqualsAndHashCode(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
-public class SysDeptDO extends BaseDO {
+public class SysDeptDO extends TenantBaseDO {
 
 
     /**
     /**
      * 部门ID
      * 部门ID

+ 2 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
 
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.Data;
@@ -15,14 +15,13 @@ import lombok.EqualsAndHashCode;
 @TableName("sys_post")
 @TableName("sys_post")
 @Data
 @Data
 @EqualsAndHashCode(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
-public class SysPostDO extends BaseDO {
+public class SysPostDO extends TenantBaseDO {
 
 
     /**
     /**
      * 岗位序号
      * 岗位序号
      */
      */
     @TableId
     @TableId
     private Long id;
     private Long id;
-
     /**
     /**
      * 岗位名称
      * 岗位名称
      */
      */

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysOperateLogDO.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.logger;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
 import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -22,7 +22,7 @@ import java.util.Map;
 @TableName(value = "sys_operate_log", autoResultMap = true)
 @TableName(value = "sys_operate_log", autoResultMap = true)
 @Data
 @Data
 @EqualsAndHashCode(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
-public class SysOperateLogDO extends BaseDO {
+public class SysOperateLogDO extends TenantBaseDO {
 
 
     /**
     /**
      * {@link #javaMethodArgs} 的最大长度
      * {@link #javaMethodArgs} 的最大长度

+ 3 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice;
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice;
 
 
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.adminserver.modules.system.enums.notice.SysNoticeTypeEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.notice.SysNoticeTypeEnum;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.Data;
@@ -16,7 +16,7 @@ import lombok.EqualsAndHashCode;
 @TableName("sys_notice")
 @TableName("sys_notice")
 @Data
 @Data
 @EqualsAndHashCode(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
-public class SysNoticeDO extends BaseDO {
+public class SysNoticeDO extends TenantBaseDO {
 
 
     /**
     /**
      * 公告ID
      * 公告ID

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java

@@ -24,7 +24,7 @@ public interface SysDeptMapper extends BaseMapperX<SysDeptDO> {
     }
     }
 
 
     default Integer selectCountByParentId(Long parentId) {
     default Integer selectCountByParentId(Long parentId) {
-        return selectCount(new QueryWrapper<SysDeptDO>().eq("parent_id", parentId));
+        return selectCount("parent_id", parentId);
     }
     }
 
 
     default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
     default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysMenuMapper.java

@@ -19,7 +19,7 @@ public interface SysMenuMapper extends BaseMapperX<SysMenuDO> {
     }
     }
 
 
     default Integer selectCountByParentId(Long parentId) {
     default Integer selectCountByParentId(Long parentId) {
-        return selectCount(new QueryWrapper<SysMenuDO>().eq("parent_id", parentId));
+        return selectCount("parent_id", parentId);
     }
     }
 
 
     default List<SysMenuDO> selectList(SysMenuListReqVO reqVO) {
     default List<SysMenuDO> selectList(SysMenuListReqVO reqVO) {

+ 44 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 租户 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface SysTenantMapper extends BaseMapperX<SysTenantDO> {
+
+    default PageResult<SysTenantDO> selectPage(SysTenantPageReqVO reqVO) {
+        return selectPage(reqVO, new QueryWrapperX<SysTenantDO>()
+                .likeIfPresent("name", reqVO.getName())
+                .likeIfPresent("contact_name", reqVO.getContactName())
+                .likeIfPresent("contact_mobile", reqVO.getContactMobile())
+                .eqIfPresent("status", reqVO.getStatus())
+                .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc("id"));
+    }
+
+    default List<SysTenantDO> selectList(SysTenantExportReqVO reqVO) {
+        return selectList(new QueryWrapperX<SysTenantDO>()
+                .likeIfPresent("name", reqVO.getName())
+                .likeIfPresent("contact_name", reqVO.getContactName())
+                .likeIfPresent("contact_mobile", reqVO.getContactMobile())
+                .eqIfPresent("status", reqVO.getStatus())
+                .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc("id"));
+    }
+
+    default SysTenantDO selectByName(String name) {
+        return selectOne("name", name);
+    }
+}

+ 3 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java

@@ -85,10 +85,12 @@ public interface SysErrorCodeConstants {
     ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
     ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
     ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板");
     ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板");
 
 
+    // ========== 租户模块 1002012000 ==========
+    ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002012000, "租户不存在");
+
     // ========== 错误码模块 1002013000 ==========
     // ========== 错误码模块 1002013000 ==========
     ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在");
     ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在");
     ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码");
     ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码");
 
 
 
 
-
 }
 }

+ 7 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaProperties.java

@@ -12,6 +12,13 @@ import java.time.Duration;
 @Data
 @Data
 public class CaptchaProperties {
 public class CaptchaProperties {
 
 
+    private static final Boolean ENABLE_DEFAULT = true;
+
+    /**
+     * 是否开启
+     * 注意,这里仅仅是后端 Server 是否校验,暂时不控制前端的逻辑
+     */
+    private Boolean enable = ENABLE_DEFAULT;
     /**
     /**
      * 验证码的过期时间
      * 验证码的过期时间
      */
      */

+ 25 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission.config;
+
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * system 模块的数据权限 Configuration
+ *
+ * @author 芋道源码
+ */
+@Configuration
+public class SysDataPermissionConfiguration {
+
+    @Bean
+    public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {
+        return rule -> {
+            rule.addDeptColumn(SysUserDO.class);
+            rule.addDeptColumn(SysDeptDO.class, "id");
+        };
+    }
+
+}

+ 4 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * system 模块的数据权限配置
+ */
+package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission;

+ 2 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/auth/SysUserSessionTimeoutJob.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.adminserver.modules.system.job.auth;
 
 
 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
+import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
@@ -13,6 +14,7 @@ import javax.annotation.Resource;
  * @author 願
  * @author 願
  */
  */
 @Component
 @Component
+@TenantJob
 @Slf4j
 @Slf4j
 public class SysUserSessionTimeoutJob implements JobHandler {
 public class SysUserSessionTimeoutJob implements JobHandler {
 
 

+ 6 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java

@@ -1,13 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.dept;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.dept;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 部门数据刷新 Message
  * 部门数据刷新 Message
+ *
+ * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysDeptRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysDeptRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 4 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java

@@ -1,13 +1,15 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.dict;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.dict;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 字典数据数据刷新 Message
  * 字典数据数据刷新 Message
  */
  */
 @Data
 @Data
-public class SysDictDataRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysDictDataRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 4 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java

@@ -1,7 +1,8 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.mail;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.mail;
 
 
-import cn.iocoder.yudao.framework.mq.core.stream.StreamMessage;
+import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.NotNull;
 import java.util.Map;
 import java.util.Map;
@@ -12,7 +13,8 @@ import java.util.Map;
  * @author 芋道源码
  * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysMailSendMessage implements StreamMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysMailSendMessage extends AbstractStreamMessage {
 
 
     /**
     /**
      * 邮箱地址
      * 邮箱地址

+ 6 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java

@@ -1,13 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 菜单数据刷新 Message
  * 菜单数据刷新 Message
+ *
+ * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysMenuRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysMenuRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 6 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java

@@ -1,13 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 角色与菜单数据刷新 Message
  * 角色与菜单数据刷新 Message
+ *
+ * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysRoleMenuRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysRoleMenuRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 6 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java

@@ -1,13 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 角色数据刷新 Message
  * 角色数据刷新 Message
+ *
+ * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysRoleRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysRoleRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 6 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java

@@ -1,13 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 短信渠道的数据刷新 Message
  * 短信渠道的数据刷新 Message
+ *
+ * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysSmsChannelRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysSmsChannelRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 6 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java

@@ -1,13 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
 package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
 
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 
 /**
 /**
  * 短信模板的数据刷新 Message
  * 短信模板的数据刷新 Message
+ *
+ * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysSmsTemplateRefreshMessage implements ChannelMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysSmsTemplateRefreshMessage extends AbstractChannelMessage {
 
 
     @Override
     @Override
     public String getChannel() {
     public String getChannel() {

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept;
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept;
 
 
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.dept.SysDeptRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.dept.SysDeptRefreshMessage;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
 public class SysDeptProducer {
 public class SysDeptProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysDeptRefreshMessage} 消息
      * 发送 {@link SysDeptRefreshMessage} 消息
      */
      */
     public void sendDeptRefreshMessage() {
     public void sendDeptRefreshMessage() {
         SysDeptRefreshMessage message = new SysDeptRefreshMessage();
         SysDeptRefreshMessage message = new SysDeptRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict;
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict;
 
 
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
 public class SysDictDataProducer {
 public class SysDictDataProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysDictDataRefreshMessage} 消息
      * 发送 {@link SysDictDataRefreshMessage} 消息
      */
      */
     public void sendDictDataRefreshMessage() {
     public void sendDictDataRefreshMessage() {
         SysDictDataRefreshMessage message = new SysDictDataRefreshMessage();
         SysDictDataRefreshMessage message = new SysDictDataRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
 
 
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysMenuRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysMenuRefreshMessage;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
 public class SysMenuProducer {
 public class SysMenuProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysMenuRefreshMessage} 消息
      * 发送 {@link SysMenuRefreshMessage} 消息
      */
      */
     public void sendMenuRefreshMessage() {
     public void sendMenuRefreshMessage() {
         SysMenuRefreshMessage message = new SysMenuRefreshMessage();
         SysMenuRefreshMessage message = new SysMenuRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
 
 
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleMenuRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleMenuRefreshMessage;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
 public class SysPermissionProducer {
 public class SysPermissionProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysRoleMenuRefreshMessage} 消息
      * 发送 {@link SysRoleMenuRefreshMessage} 消息
      */
      */
     public void sendRoleMenuRefreshMessage() {
     public void sendRoleMenuRefreshMessage() {
         SysRoleMenuRefreshMessage message = new SysRoleMenuRefreshMessage();
         SysRoleMenuRefreshMessage message = new SysRoleMenuRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
 
 
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleRefreshMessage;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -16,14 +15,14 @@ import javax.annotation.Resource;
 public class SysRoleProducer {
 public class SysRoleProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysRoleRefreshMessage} 消息
      * 发送 {@link SysRoleRefreshMessage} 消息
      */
      */
     public void sendRoleRefreshMessage() {
     public void sendRoleRefreshMessage() {
         SysRoleRefreshMessage message = new SysRoleRefreshMessage();
         SysRoleRefreshMessage message = new SysRoleRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 4 - 7
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java

@@ -1,15 +1,12 @@
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms;
 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms;
 
 
-import cn.iocoder.yudao.framework.common.core.KeyValue;
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsChannelRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsChannelRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage;
 import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
-import java.util.List;
 
 
 /**
 /**
  * Sms 短信相关消息的 Producer
  * Sms 短信相关消息的 Producer
@@ -22,14 +19,14 @@ import java.util.List;
 public class SysSmsProducer {
 public class SysSmsProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysSmsChannelRefreshMessage} 消息
      * 发送 {@link SysSmsChannelRefreshMessage} 消息
      */
      */
     public void sendSmsChannelRefreshMessage() {
     public void sendSmsChannelRefreshMessage() {
         SysSmsChannelRefreshMessage message = new SysSmsChannelRefreshMessage();
         SysSmsChannelRefreshMessage message = new SysSmsChannelRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
     /**
     /**
@@ -37,7 +34,7 @@ public class SysSmsProducer {
      */
      */
     public void sendSmsTemplateRefreshMessage() {
     public void sendSmsTemplateRefreshMessage() {
         SysSmsTemplateRefreshMessage message = new SysSmsTemplateRefreshMessage();
         SysSmsTemplateRefreshMessage message = new SysSmsTemplateRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

+ 42 - 42
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java

@@ -1,21 +1,17 @@
 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
 package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
 
 
-import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
-import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
-import cn.iocoder.yudao.framework.security.core.LoginUser;
-import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialBindReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
+import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
@@ -23,7 +19,7 @@ import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -45,16 +41,14 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 import org.springframework.util.Assert;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
+import java.util.Collections;
 import java.util.List;
 import java.util.List;
-import java.util.Optional;
 import java.util.Objects;
 import java.util.Objects;
 import java.util.Set;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
-import static java.util.Collections.EMPTY_LIST;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static java.util.Collections.singleton;
 import static java.util.Collections.singleton;
 
 
 /**
 /**
@@ -66,6 +60,8 @@ import static java.util.Collections.singleton;
 @Slf4j
 @Slf4j
 public class SysAuthServiceImpl implements SysAuthService {
 public class SysAuthServiceImpl implements SysAuthService {
 
 
+    private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.ADMIN;
+
     @Resource
     @Resource
     @Lazy // 延迟加载,因为存在相互依赖的问题
     @Lazy // 延迟加载,因为存在相互依赖的问题
     private AuthenticationManager authenticationManager;
     private AuthenticationManager authenticationManager;
@@ -83,11 +79,10 @@ public class SysAuthServiceImpl implements SysAuthService {
     @Resource
     @Resource
     private SysUserSessionCoreService userSessionCoreService;
     private SysUserSessionCoreService userSessionCoreService;
     @Resource
     @Resource
-    private SysPostService sysPostService;
-    private SysSocialService socialService;
+    private SysPostService postService;
+    @Resource
+    private SysSocialCoreService socialService;
 
 
-    // TODO @timfruit:静态枚举类,需要都大写,例如说 USER_TYPE_ENUM;静态变量,放在普通变量前面;这个实践不错哈。
-    private static final UserTypeEnum userTypeEnum = UserTypeEnum.ADMIN;
 
 
     @Override
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@@ -97,9 +92,7 @@ public class SysAuthServiceImpl implements SysAuthService {
             throw new UsernameNotFoundException(username);
             throw new UsernameNotFoundException(username);
         }
         }
         // 创建 LoginUser 对象
         // 创建 LoginUser 对象
-        LoginUser loginUser =  SysAuthConvert.INSTANCE.convert(user);
-        loginUser.setPostIds(user.getPostIds());
-        return loginUser;
+        return this.buildLoginUser(user);
     }
     }
 
 
     @Override
     @Override
@@ -112,9 +105,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
         this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
 
 
         // 创建 LoginUser 对象
         // 创建 LoginUser 对象
-        LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
-        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
-        return loginUser;
+        return this.buildLoginUser(user);
     }
     }
 
 
     @Override
     @Override
@@ -122,25 +113,28 @@ public class SysAuthServiceImpl implements SysAuthService {
         // 判断验证码是否正确
         // 判断验证码是否正确
         this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
         this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
 
 
-        // 使用账号密码,进行登录
+        // 使用账号密码,进行登录
         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
-        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
-        loginUser.setGroups(this.getUserPosts(loginUser.getPostIds()));
+
         // 缓存登陆用户到 Redis 中,返回 sessionId 编号
         // 缓存登陆用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
     }
     }
 
 
-
     private List<String> getUserPosts(Set<Long> postIds) {
     private List<String> getUserPosts(Set<Long> postIds) {
-        return Optional.ofNullable(postIds).map(ids->
-               sysPostService.getPosts(ids).stream().map(post -> post.getCode()).collect(Collectors.toList())
-        ).orElse(EMPTY_LIST);
+        if (CollUtil.isEmpty(postIds)) {
+            return Collections.emptyList();
+        }
+        return convertList(postService.getPosts(postIds), SysPostDO::getCode);
     }
     }
 
 
     private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
     private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
+        // 如果验证码关闭,则不进行校验
+        if (!captchaService.isCaptchaEnable()) {
+            return;
+        }
+        // 验证码不存在
         final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
         final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
         String code = captchaService.getCaptchaCode(captchaUUID);
         String code = captchaService.getCaptchaCode(captchaUUID);
-        // 验证码不存在
         if (code == null) {
         if (code == null) {
             // 创建登录失败日志(验证码不存在)
             // 创建登录失败日志(验证码不存在)
             this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
             this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
@@ -222,7 +216,7 @@ public class SysAuthServiceImpl implements SysAuthService {
 
 
         // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
         // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
         String unionId = socialService.getAuthUserUnionId(authUser);
         String unionId = socialService.getAuthUserUnionId(authUser);
-        List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, userTypeEnum);
+        List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM);
         if (CollUtil.isEmpty(socialUsers)) {
         if (CollUtil.isEmpty(socialUsers)) {
             throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
             throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
         }
         }
@@ -235,11 +229,10 @@ public class SysAuthServiceImpl implements SysAuthService {
         this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
         this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
 
 
         // 创建 LoginUser 对象
         // 创建 LoginUser 对象
-        LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
-        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
+        LoginUser loginUser = this.buildLoginUser(user);
 
 
         // 绑定社交用户(更新)
         // 绑定社交用户(更新)
-        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
 
 
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -253,10 +246,9 @@ public class SysAuthServiceImpl implements SysAuthService {
 
 
         // 使用账号密码,进行登录。
         // 使用账号密码,进行登录。
         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
         LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
-        loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
 
 
         // 绑定社交用户(新增)
         // 绑定社交用户(新增)
-        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM);
 
 
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         // 缓存登录用户到 Redis 中,返回 sessionId 编号
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
         return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -269,7 +261,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         Assert.notNull(authUser, "授权用户不为空");
         Assert.notNull(authUser, "授权用户不为空");
 
 
         // 绑定社交用户(新增)
         // 绑定社交用户(新增)
-        socialService.bindSocialUser(userId, reqVO.getType(), authUser, userTypeEnum);
+        socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM);
     }
     }
 
 
     @Override
     @Override
@@ -290,7 +282,7 @@ public class SysAuthServiceImpl implements SysAuthService {
         reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
         reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
         reqDTO.setTraceId(TracerUtils.getTraceId());
         reqDTO.setTraceId(TracerUtils.getTraceId());
         reqDTO.setUserId(userId);
         reqDTO.setUserId(userId);
-        reqDTO.setUserType(userTypeEnum.getValue());
+        reqDTO.setUserType(USER_TYPE_ENUM.getValue());
         reqDTO.setUsername(username);
         reqDTO.setUsername(username);
         reqDTO.setUserAgent(ServletUtils.getUserAgent());
         reqDTO.setUserAgent(ServletUtils.getUserAgent());
         reqDTO.setUserIp(ServletUtils.getClientIP());
         reqDTO.setUserIp(ServletUtils.getClientIP());
@@ -306,15 +298,14 @@ public class SysAuthServiceImpl implements SysAuthService {
             return null;
             return null;
         }
         }
         // 刷新 LoginUser 缓存
         // 刷新 LoginUser 缓存
-        this.refreshLoginUserCache(token, loginUser);
-        return loginUser;
+        return this.refreshLoginUserCache(token, loginUser);
     }
     }
 
 
-    private void refreshLoginUserCache(String token, LoginUser loginUser) {
+    private LoginUser refreshLoginUserCache(String token, LoginUser loginUser) {
         // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
         // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
         if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
         if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
                 userSessionCoreService.getSessionTimeoutMillis() / 3) {
                 userSessionCoreService.getSessionTimeoutMillis() / 3) {
-            return;
+            return loginUser;
         }
         }
 
 
         // 重新加载 SysUserDO 信息
         // 重新加载 SysUserDO 信息
@@ -324,9 +315,18 @@ public class SysAuthServiceImpl implements SysAuthService {
         }
         }
 
 
         // 刷新 LoginUser 缓存
         // 刷新 LoginUser 缓存
+        LoginUser newLoginUser= this.buildLoginUser(user);
+        userSessionCoreService.refreshUserSession(token, newLoginUser);
+        return newLoginUser;
+    }
+
+    private LoginUser buildLoginUser(SysUserDO user) {
+        LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
+        // 补全字段
         loginUser.setDeptId(user.getDeptId());
         loginUser.setDeptId(user.getDeptId());
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
         loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
-        userSessionCoreService.refreshUserSession(token, loginUser);
+        loginUser.setGroups(this.getUserPosts(user.getPostIds()));
+        return loginUser;
     }
     }
 
 
 }
 }

+ 7 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java

@@ -14,6 +14,13 @@ public interface SysCaptchaService {
      */
      */
     SysCaptchaImageRespVO getCaptchaImage();
     SysCaptchaImageRespVO getCaptchaImage();
 
 
+    /**
+     * 是否开启图片验证码
+     *
+     * @return 是否
+     */
+    Boolean isCaptchaEnable();
+
     /**
     /**
      * 获得 uuid 对应的验证码
      * 获得 uuid 对应的验证码
      *
      *

+ 5 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java

@@ -35,6 +35,11 @@ public class SysCaptchaServiceImpl implements SysCaptchaService {
         return SysCaptchaConvert.INSTANCE.convert(uuid, captcha);
         return SysCaptchaConvert.INSTANCE.convert(uuid, captcha);
     }
     }
 
 
+    @Override
+    public Boolean isCaptchaEnable() {
+        return captchaProperties.getEnable();
+    }
+
     @Override
     @Override
     public String getCaptchaCode(String uuid) {
     public String getCaptchaCode(String uuid) {
         return captchaRedisDAO.get(uuid);
         return captchaRedisDAO.get(uuid);

+ 8 - 12
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysDeptServiceImpl.java

@@ -169,9 +169,12 @@ public class SysDeptServiceImpl implements SysDeptService {
 
 
     @Override
     @Override
     public List<SysDeptDO> getDeptsByParentIdFromCache(Long parentId, boolean recursive) {
     public List<SysDeptDO> getDeptsByParentIdFromCache(Long parentId, boolean recursive) {
-        List<SysDeptDO> result = new ArrayList<>();
+        if (parentId == null) {
+            return Collections.emptyList();
+        }
+        List<SysDeptDO> result = new ArrayList<>(); // TODO 芋艿:待优化,新增缓存,避免每次遍历的计算
         // 递归,简单粗暴
         // 递归,简单粗暴
-        this.listDeptsByParentIdFromCache(result, parentId,
+        this.getDeptsByParentIdFromCache(result, parentId,
                 recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次
                 recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次
                 parentDeptCache);
                 parentDeptCache);
         return result;
         return result;
@@ -185,8 +188,8 @@ public class SysDeptServiceImpl implements SysDeptService {
      * @param recursiveCount 递归次数
      * @param recursiveCount 递归次数
      * @param parentDeptMap 父部门 Map,使用缓存,避免变化
      * @param parentDeptMap 父部门 Map,使用缓存,避免变化
      */
      */
-    private void listDeptsByParentIdFromCache(List<SysDeptDO> result, Long parentId, int recursiveCount,
-                                              Multimap<Long, SysDeptDO> parentDeptMap) {
+    private void getDeptsByParentIdFromCache(List<SysDeptDO> result, Long parentId, int recursiveCount,
+                                             Multimap<Long, SysDeptDO> parentDeptMap) {
         // 递归次数为 0,结束!
         // 递归次数为 0,结束!
         if (recursiveCount == 0) {
         if (recursiveCount == 0) {
             return;
             return;
@@ -198,7 +201,7 @@ public class SysDeptServiceImpl implements SysDeptService {
         }
         }
         result.addAll(depts);
         result.addAll(depts);
         // 继续递归
         // 继续递归
-        depts.forEach(dept -> listDeptsByParentIdFromCache(result, dept.getId(),
+        depts.forEach(dept -> getDeptsByParentIdFromCache(result, dept.getId(),
                 recursiveCount - 1, parentDeptMap));
                 recursiveCount - 1, parentDeptMap));
     }
     }
 
 
@@ -264,11 +267,4 @@ public class SysDeptServiceImpl implements SysDeptService {
         }
         }
     }
     }
 
 
-//    @Override
-//    @DataScope(deptAlias = "d")
-//    public List<SysDept> selectDeptList(SysDept dept)
-//    {
-//        return deptMapper.selectDeptList(dept);
-//    }
-
 }
 }

+ 2 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.adminserver.modules.system.service.permission;
 package cn.iocoder.yudao.adminserver.modules.system.service.permission;
 
 
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
 import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService;
 import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
 import org.springframework.lang.Nullable;
 import org.springframework.lang.Nullable;
@@ -15,7 +16,7 @@ import java.util.Set;
  *
  *
  * @author 芋道源码
  * @author 芋道源码
  */
  */
-public interface SysPermissionService extends SecurityPermissionFrameworkService {
+public interface SysPermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService {
 
 
     /**
     /**
      * 初始化权限的本地缓存
      * 初始化权限的本地缓存

+ 70 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java

@@ -3,19 +3,25 @@ package cn.iocoder.yudao.adminserver.modules.system.service.permission.impl;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ArrayUtil;
-import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
-import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
-import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
+import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
+import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
+import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Sets;
@@ -39,6 +45,11 @@ import java.util.*;
 @Slf4j
 @Slf4j
 public class SysPermissionServiceImpl implements SysPermissionService {
 public class SysPermissionServiceImpl implements SysPermissionService {
 
 
+    /**
+     * LoginUser 的 Context 缓存 Key
+     */
+    public static final String CONTEXT_KEY = SysPermissionServiceImpl.class.getSimpleName();
+
     /**
     /**
      * 定时执行 {@link #schedulePeriodicRefresh()} 的周期
      * 定时执行 {@link #schedulePeriodicRefresh()} 的周期
      * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
      * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
@@ -75,6 +86,8 @@ public class SysPermissionServiceImpl implements SysPermissionService {
     private SysRoleService roleService;
     private SysRoleService roleService;
     @Resource
     @Resource
     private SysMenuService menuService;
     private SysMenuService menuService;
+    @Resource
+    private SysDeptService deptService;
 
 
     @Resource
     @Resource
     private SysPermissionProducer permissionProducer;
     private SysPermissionProducer permissionProducer;
@@ -329,4 +342,58 @@ public class SysPermissionServiceImpl implements SysPermissionService {
         return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
         return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
     }
     }
 
 
+    @Override
+    public DeptDataPermissionRespDTO getDeptDataPermission(LoginUser loginUser) {
+        // 判断是否 context 已经缓存
+        DeptDataPermissionRespDTO result = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
+        if (result != null) {
+            return result;
+        }
+
+        // 创建 DeptDataPermissionRespDTO 对象
+        result = new DeptDataPermissionRespDTO();
+        List<SysRoleDO> roles = roleService.getRolesFromCache(loginUser.getRoleIds());
+        for (SysRoleDO role : roles) {
+            // 为空时,跳过
+            if (role.getDataScope() == null) {
+                continue;
+            }
+            // 情况一,ALL
+            if (Objects.equals(role.getDataScope(), DataScopeEnum.ALL.getScope())) {
+                result.setAll(true);
+                continue;
+            }
+            // 情况二,DEPT_CUSTOM
+            if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_CUSTOM.getScope())) {
+                CollUtil.addAll(result.getDeptIds(), role.getDataScopeDeptIds());
+                // 自定义可见部门时,保证可以看到自己所在的部门。否则,一些场景下可能会有问题。
+                // 例如说,登录时,基于 t_user 的 username 查询会可能被 dept_id 过滤掉
+                CollUtil.addAll(result.getDeptIds(), loginUser.getDeptId());
+                continue;
+            }
+            // 情况三,DEPT_ONLY
+            if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_ONLY.getScope())) {
+                CollectionUtils.addIfNotNull(result.getDeptIds(), loginUser.getDeptId());
+                continue;
+            }
+            // 情况四,DEPT_DEPT_AND_CHILD
+            if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) {
+                List<SysDeptDO> depts = deptService.getDeptsByParentIdFromCache(loginUser.getDeptId(), true);
+                CollUtil.addAll(result.getDeptIds(), CollectionUtils.convertList(depts, SysDeptDO::getId));
+                continue;
+            }
+            // 情况五,SELF
+            if (Objects.equals(role.getDataScope(), DataScopeEnum.SELF.getScope())) {
+                result.setSelf(true);
+                continue;
+            }
+            // 未知情况,error log 即可
+            log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", loginUser.getId(), JsonUtils.toJsonString(result));
+        }
+
+        // 添加到缓存,并返回
+        loginUser.setContext(CONTEXT_KEY, result);
+        return result;
+    }
+
 }
 }

+ 2 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysRoleServiceImpl.java

@@ -18,6 +18,7 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.permission.SysRoleTypeE
 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysRoleProducer;
 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysRoleProducer;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
+import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
@@ -127,6 +128,7 @@ public class SysRoleServiceImpl implements SysRoleService {
         SysRoleDO role = SysRoleConvert.INSTANCE.convert(reqVO);
         SysRoleDO role = SysRoleConvert.INSTANCE.convert(reqVO);
         role.setType(SysRoleTypeEnum.CUSTOM.getType());
         role.setType(SysRoleTypeEnum.CUSTOM.getType());
         role.setStatus(CommonStatusEnum.ENABLE.getStatus());
         role.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限
         roleMapper.insert(role);
         roleMapper.insert(role);
         // 发送刷新消息
         // 发送刷新消息
         roleProducer.sendRoleRefreshMessage();
         roleProducer.sendRoleRefreshMessage();

+ 83 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java

@@ -0,0 +1,83 @@
+package cn.iocoder.yudao.adminserver.modules.system.service.tenant;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 租户 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface SysTenantService {
+
+    /**
+     * 创建租户
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createTenant(@Valid SysTenantCreateReqVO createReqVO);
+
+    /**
+     * 更新租户
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateTenant(@Valid SysTenantUpdateReqVO updateReqVO);
+
+    /**
+     * 删除租户
+     *
+     * @param id 编号
+     */
+    void deleteTenant(Long id);
+
+    /**
+     * 获得租户
+     *
+     * @param id 编号
+     * @return 租户
+     */
+    SysTenantDO getTenant(Long id);
+
+    /**
+     * 获得租户列表
+     *
+     * @param ids 编号
+     * @return 租户列表
+     */
+    List<SysTenantDO> getTenantList(Collection<Long> ids);
+
+    /**
+     * 获得租户分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 租户分页
+     */
+    PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO);
+
+    /**
+     * 获得租户列表, 用于 Excel 导出
+     *
+     * @param exportReqVO 查询条件
+     * @return 租户列表
+     */
+    List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO);
+
+    /**
+     * 获得名字对应的租户
+     *
+     * @param name 组户名
+     * @return 租户
+     */
+    SysTenantDO getTenantByName(String name);
+
+}

+ 91 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java

@@ -0,0 +1,91 @@
+package cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
+import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper;
+import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+
+/**
+ * 租户 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class SysTenantServiceImpl implements SysTenantService {
+
+    @Resource
+    private SysTenantMapper tenantMapper;
+
+    @Override
+    public Long createTenant(SysTenantCreateReqVO createReqVO) {
+        // 插入
+        SysTenantDO tenant = SysTenantConvert.INSTANCE.convert(createReqVO);
+        tenantMapper.insert(tenant);
+        // 返回
+        return tenant.getId();
+    }
+
+    @Override
+    public void updateTenant(SysTenantUpdateReqVO updateReqVO) {
+        // 校验存在
+        this.validateTenantExists(updateReqVO.getId());
+        // 更新
+        SysTenantDO updateObj = SysTenantConvert.INSTANCE.convert(updateReqVO);
+        tenantMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteTenant(Long id) {
+        // 校验存在
+        this.validateTenantExists(id);
+        // 删除
+        tenantMapper.deleteById(id);
+    }
+
+    private void validateTenantExists(Long id) {
+        if (tenantMapper.selectById(id) == null) {
+            throw exception(TENANT_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public SysTenantDO getTenant(Long id) {
+        return tenantMapper.selectById(id);
+    }
+
+    @Override
+    public List<SysTenantDO> getTenantList(Collection<Long> ids) {
+        return tenantMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO) {
+        return tenantMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO) {
+        return tenantMapper.selectList(exportReqVO);
+    }
+
+    @Override
+    public SysTenantDO getTenantByName(String name) {
+        return tenantMapper.selectByName(name);
+    }
+
+}

+ 5 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenEngine.java

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties;
 import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties;
+import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -119,6 +120,8 @@ public class ToolCodegenEngine {
     private void initGlobalBindingMap() {
     private void initGlobalBindingMap() {
         // 全局配置
         // 全局配置
         globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
         globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
+        globalBindingMap.put("baseFrameworkPackage", StrUtil.subBefore(codegenProperties.getBasePackage(),
+                '.', true) + '.' + "framework");
         // 全局 Java Bean
         // 全局 Java Bean
         globalBindingMap.put("CommonResultClassName", CommonResult.class.getName());
         globalBindingMap.put("CommonResultClassName", CommonResult.class.getName());
         globalBindingMap.put("PageResultClassName", PageResult.class.getName());
         globalBindingMap.put("PageResultClassName", PageResult.class.getName());
@@ -134,6 +137,7 @@ public class ToolCodegenEngine {
         globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName());
         globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName());
         globalBindingMap.put("DateUtilsClassName", DateUtils.class.getName());
         globalBindingMap.put("DateUtilsClassName", DateUtils.class.getName());
         globalBindingMap.put("ExcelUtilsClassName", ExcelUtils.class.getName());
         globalBindingMap.put("ExcelUtilsClassName", ExcelUtils.class.getName());
+        globalBindingMap.put("ObjectUtilsClassName", ObjectUtils.class.getName());
         globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
         globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
         globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
         globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
         globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
         globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
@@ -191,7 +195,7 @@ public class ToolCodegenEngine {
     }
     }
 
 
     private static String javaFilePath(String path) {
     private static String javaFilePath(String path) {
-        return "java/${basePackage}/${table.moduleName}/" + path + ".java";
+        return "java/${basePackage}/modules/${table.moduleName}/" + path + ".java";
     }
     }
 
 
     private static String vueTemplatePath(String path) {
     private static String vueTemplatePath(String path) {

+ 11 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenSQLParser.java

@@ -16,6 +16,7 @@ import org.apache.commons.collections4.keyvalue.DefaultKeyValue;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
+import java.util.Objects;
 
 
 import static com.alibaba.druid.sql.SQLUtils.normalize;
 import static com.alibaba.druid.sql.SQLUtils.normalize;
 
 
@@ -63,10 +64,17 @@ public class ToolCodegenSQLParser {
     private static ToolSchemaTableDO parseTable(SQLCreateTableStatement statement) {
     private static ToolSchemaTableDO parseTable(SQLCreateTableStatement statement) {
         return ToolSchemaTableDO.builder()
         return ToolSchemaTableDO.builder()
                 .tableName(statement.getTableSource().getTableName(true))
                 .tableName(statement.getTableSource().getTableName(true))
-                .tableComment(((SQLCharExpr) statement.getComment()).getText())
+                .tableComment(getCommentText(statement))
                 .build();
                 .build();
     }
     }
 
 
+    private static String getCommentText(SQLCreateTableStatement statement) {
+        if (statement == null || statement.getComment() == null) {
+            return "";
+        }
+        return ((SQLCharExpr) statement.getComment()).getText();
+    }
+
     private static List<ToolSchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {
     private static List<ToolSchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {
         List<ToolSchemaColumnDO> columns = new ArrayList<>();
         List<ToolSchemaColumnDO> columns = new ArrayList<>();
         statement.getTableElementList().forEach(element -> parseColumn(columns, element));
         statement.getTableElementList().forEach(element -> parseColumn(columns, element));
@@ -97,7 +105,8 @@ public class ToolCodegenSQLParser {
         columns.add(ToolSchemaColumnDO.builder()
         columns.add(ToolSchemaColumnDO.builder()
                 .columnName(normalize(definition.getColumnName()))
                 .columnName(normalize(definition.getColumnName()))
                 .columnType(definition.getDataType().toString())
                 .columnType(definition.getDataType().toString())
-                .columnComment(normalize(definition.getComment().toString()))
+                .columnComment(Objects.isNull(definition.getComment()) ? ""
+                        : normalize(definition.getComment().toString()))
                 .nullable(!text.contains(" NOT NULL"))
                 .nullable(!text.contains(" NOT NULL"))
                 .primaryKey(false)
                 .primaryKey(false)
                 .autoIncrement(text.contains("AUTO_INCREMENT"))
                 .autoIncrement(text.contains("AUTO_INCREMENT"))

+ 1 - 0
yudao-admin-server/src/main/resources/application-dev.yaml

@@ -66,6 +66,7 @@ spring:
 # Quartz 配置项,对应 QuartzProperties 配置类
 # Quartz 配置项,对应 QuartzProperties 配置类
 spring:
 spring:
   quartz:
   quartz:
+    auto-startup: true # 测试环境,需要开启 Job
     scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
     scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
     job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
     job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
     wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
     wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true

+ 3 - 0
yudao-admin-server/src/main/resources/application-local.yaml

@@ -80,6 +80,7 @@ spring:
 # Quartz 配置项,对应 QuartzProperties 配置类
 # Quartz 配置项,对应 QuartzProperties 配置类
 spring:
 spring:
   quartz:
   quartz:
+    auto-startup: false # 本地开发环境,尽量不要开启 Job
     scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
     scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
     job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
     job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
     wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
     wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
@@ -166,6 +167,8 @@ logging:
 
 
 # 芋道配置项,设置当前项目所有自定义的配置
 # 芋道配置项,设置当前项目所有自定义的配置
 yudao:
 yudao:
+  captcha:
+    enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试
   security:
   security:
     token-header: Authorization
     token-header: Authorization
     token-secret: abcdefghijklmnopqrstuvwxyz
     token-secret: abcdefghijklmnopqrstuvwxyz

+ 3 - 1
yudao-admin-server/src/main/resources/application.yaml

@@ -22,7 +22,7 @@ spring:
 
 
 # MyBatis Plus 的配置项
 # MyBatis Plus 的配置项
 mybatis-plus:
 mybatis-plus:
-#  在 mybatis-config/mybatis-config.xml 中设置
+#  在 mybatis-config/mybatis-config.xml 中设置 TODO jason:看看有没其它解决方案
 #  configuration:
 #  configuration:
 #    map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
 #    map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
 #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
 #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
@@ -74,5 +74,7 @@ yudao:
       - cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants
       - cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants
       - cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants
       - cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants
       - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants
       - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants
+  tenant: # 多租户相关配置项
+    tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置
 
 
 debug: false
 debug: false

+ 5 - 5
yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm

@@ -10,7 +10,6 @@ import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.
 import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*;
 import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*;
 import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
 import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
 import ${basePackage}.modules.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
 import ${basePackage}.modules.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
-import ${basePackage}.util.object.ObjectUtils;
 import ${PageResultClassName};
 import ${PageResultClassName};
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
@@ -19,9 +18,10 @@ import java.util.*;
 
 
 import static cn.hutool.core.util.RandomUtil.*;
 import static cn.hutool.core.util.RandomUtil.*;
 import static ${basePackage}.modules.${table.moduleName}.enums.${simpleModuleName_upperFirst}ErrorCodeConstants.*;
 import static ${basePackage}.modules.${table.moduleName}.enums.${simpleModuleName_upperFirst}ErrorCodeConstants.*;
-import static ${basePackage}.util.AssertUtils.*;
-import static ${basePackage}.util.RandomUtils.*;
-import static ${basePackage}.util.date.DateUtils.*;
+import static ${baseFrameworkPackage}.test.core.util.AssertUtils.*;
+import static ${baseFrameworkPackage}.test.core.util.RandomUtils.*;
+import static ${ObjectUtilsClassName}.*;
+import static ${DateUtilsClassName}.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.*;
 import static org.mockito.Mockito.*;
 
 
@@ -41,7 +41,7 @@ import static org.mockito.Mockito.*;
        #if (${column.listOperation})
        #if (${column.listOperation})
        #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写
        #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写
        // 测试 ${column.javaField} 不匹配
        // 测试 ${column.javaField} 不匹配
-       ${classNameVar}Mapper.insert(ObjectUtils.clone(db${simpleClassName}, o -> o.set$JavaField(null)));
+       ${classNameVar}Mapper.insert(cloneIgnoreId(db${simpleClassName}, o -> o.set$JavaField(null)));
        #end
        #end
        #end
        #end
        // 准备参数
        // 准备参数

+ 1 - 1
yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml

@@ -6,7 +6,7 @@
     <settings>
     <settings>
         <setting name="lazyLoadingEnabled" value="false" />
         <setting name="lazyLoadingEnabled" value="false" />
         <setting name="mapUnderscoreToCamelCase" value="true"/>
         <setting name="mapUnderscoreToCamelCase" value="true"/>
-<!--        <setting name="logImpl" value="STDOUT_LOGGING"/>-->
+        <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/> <!-- 如果不想打 SQL 日志,可以注释掉 -->
     </settings>
     </settings>
     <typeAliases>
     <typeAliases>
         <typeAlias type="org.activiti.engine.impl.persistence.ByteArrayRefTypeHandler" alias="ByteArrayRefTypeHandler"/>
         <typeAlias type="org.activiti.engine.impl.persistence.ByteArrayRefTypeHandler" alias="ByteArrayRefTypeHandler"/>

+ 8 - 8
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigServiceTest.java

@@ -172,13 +172,13 @@ public class InfConfigServiceTest extends BaseDbUnitTest {
         });
         });
         configMapper.insert(dbConfig);
         configMapper.insert(dbConfig);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setName("土豆")));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setName("土豆")));
         // 测试 key 不匹配
         // 测试 key 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setKey("tudou")));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou")));
         // 测试 type 不匹配
         // 测试 type 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
         // 准备参数
         // 准备参数
         InfConfigPageReqVO reqVO = new InfConfigPageReqVO();
         InfConfigPageReqVO reqVO = new InfConfigPageReqVO();
         reqVO.setName("艿");
         reqVO.setName("艿");
@@ -206,13 +206,13 @@ public class InfConfigServiceTest extends BaseDbUnitTest {
         });
         });
         configMapper.insert(dbConfig);
         configMapper.insert(dbConfig);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setName("土豆")));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setName("土豆")));
         // 测试 key 不匹配
         // 测试 key 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setKey("tudou")));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou")));
         // 测试 type 不匹配
         // 测试 type 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
+        configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
         // 准备参数
         // 准备参数
         InfConfigExportReqVO reqVO = new InfConfigExportReqVO();
         InfConfigExportReqVO reqVO = new InfConfigExportReqVO();
         reqVO.setName("艿");
         reqVO.setName("艿");

+ 5 - 5
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java

@@ -2,10 +2,10 @@ package cn.iocoder.yudao.adminserver.modules.infra.service.file;
 
 
 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
 import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
 import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
+import cn.iocoder.yudao.adminserver.modules.infra.service.file.impl.InfFileServiceImpl;
 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
 import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper;
 import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper;
 import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties;
 import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties;
-import cn.iocoder.yudao.coreservice.modules.infra.service.file.impl.InfFileCoreServiceImpl;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
@@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 
-@Import({InfFileCoreServiceImpl.class, FileProperties.class})
+@Import({InfFileServiceImpl.class, FileProperties.class})
 public class InfFileServiceTest extends BaseDbUnitTest {
 public class InfFileServiceTest extends BaseDbUnitTest {
 
 
     @Resource
     @Resource
@@ -41,14 +41,14 @@ public class InfFileServiceTest extends BaseDbUnitTest {
         });
         });
         fileMapper.insert(dbFile);
         fileMapper.insert(dbFile);
         // 测试 id 不匹配
         // 测试 id 不匹配
-        fileMapper.insert(ObjectUtils.clone(dbFile, o -> o.setId("tudou")));
+        fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setId("tudou")));
         // 测试 type 不匹配
         // 测试 type 不匹配
-        fileMapper.insert(ObjectUtils.clone(dbFile, o -> {
+        fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
             o.setId("yudao02");
             o.setId("yudao02");
             o.setType("png");
             o.setType("png");
         }));
         }));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        fileMapper.insert(ObjectUtils.clone(dbFile, o -> {
+        fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
             o.setId("yudao03");
             o.setId("yudao03");
             o.setCreateTime(buildTime(2020, 1, 15));
             o.setCreateTime(buildTime(2020, 1, 15));
         }));
         }));

+ 11 - 11
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogServiceTest.java

@@ -84,7 +84,7 @@ public class InfJobLogServiceTest extends BaseDbUnitTest {
             o.setExecuteIndex(1);
             o.setExecuteIndex(1);
             o.setStatus(randomEle(InfJobLogStatusEnum.values()).getStatus()); // 保证 status 的范围
             o.setStatus(randomEle(InfJobLogStatusEnum.values()).getStatus()); // 保证 status 的范围
         });
         });
-        InfJobLogDO cloneJobLog = ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString()));
+        InfJobLogDO cloneJobLog = ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString()));
         jobLogMapper.insert(dbJobLog);
         jobLogMapper.insert(dbJobLog);
         // 测试 handlerName 不匹配
         // 测试 handlerName 不匹配
         jobLogMapper.insert(cloneJobLog);
         jobLogMapper.insert(cloneJobLog);
@@ -111,15 +111,15 @@ public class InfJobLogServiceTest extends BaseDbUnitTest {
         });
         });
         jobLogMapper.insert(dbJobLog);
         jobLogMapper.insert(dbJobLog);
         // 测试 jobId 不匹配
         // 测试 jobId 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId())));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setJobId(randomLongId())));
         // 测试 handlerName 不匹配
         // 测试 handlerName 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())));
         // 测试 beginTime 不匹配
         // 测试 beginTime 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
         // 测试 endTime 不匹配
         // 测试 endTime 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
         // 准备参数
         // 准备参数
         InfJobLogPageReqVO reqVo = new InfJobLogPageReqVO();
         InfJobLogPageReqVO reqVo = new InfJobLogPageReqVO();
         reqVo.setJobId(dbJobLog.getJobId());
         reqVo.setJobId(dbJobLog.getJobId());
@@ -147,15 +147,15 @@ public class InfJobLogServiceTest extends BaseDbUnitTest {
         });
         });
         jobLogMapper.insert(dbJobLog);
         jobLogMapper.insert(dbJobLog);
         // 测试 jobId 不匹配
         // 测试 jobId 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId())));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setJobId(randomLongId())));
         // 测试 handlerName 不匹配
         // 测试 handlerName 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())));
         // 测试 beginTime 不匹配
         // 测试 beginTime 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
         // 测试 endTime 不匹配
         // 测试 endTime 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
+        jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
         // 准备参数
         // 准备参数
         InfJobLogExportReqVO reqVo = new InfJobLogExportReqVO();
         InfJobLogExportReqVO reqVo = new InfJobLogExportReqVO();
         reqVo.setJobId(dbJobLog.getJobId());
         reqVo.setJobId(dbJobLog.getJobId());

+ 7 - 7
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobServiceTest.java

@@ -230,7 +230,7 @@ public class InfJobServiceTest extends BaseDbUnitTest {
         InfJobDO dbJob = randomPojo(InfJobDO.class, o -> {
         InfJobDO dbJob = randomPojo(InfJobDO.class, o -> {
             o.setStatus(randomEle(InfJobStatusEnum.values()).getStatus()); // 保证 status 的范围
             o.setStatus(randomEle(InfJobStatusEnum.values()).getStatus()); // 保证 status 的范围
         });
         });
-        InfJobDO cloneJob = ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString()));
+        InfJobDO cloneJob = ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString()));
         jobMapper.insert(dbJob);
         jobMapper.insert(dbJob);
         // 测试 handlerName 不匹配
         // 测试 handlerName 不匹配
         jobMapper.insert(cloneJob);
         jobMapper.insert(cloneJob);
@@ -255,11 +255,11 @@ public class InfJobServiceTest extends BaseDbUnitTest {
         });
         });
         jobMapper.insert(dbJob);
         jobMapper.insert(dbJob);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆")));
+        jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setName("土豆")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
+        jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
         // 测试 handlerName 不匹配
         // 测试 handlerName 不匹配
-        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())));
+        jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString())));
         // 准备参数
         // 准备参数
         InfJobPageReqVO reqVo = new InfJobPageReqVO();
         InfJobPageReqVO reqVo = new InfJobPageReqVO();
         reqVo.setName("定时");
         reqVo.setName("定时");
@@ -283,11 +283,11 @@ public class InfJobServiceTest extends BaseDbUnitTest {
         });
         });
         jobMapper.insert(dbJob);
         jobMapper.insert(dbJob);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆")));
+        jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setName("土豆")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
+        jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
         // 测试 handlerName 不匹配
         // 测试 handlerName 不匹配
-        jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())));
+        jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString())));
         // 准备参数
         // 准备参数
         InfJobExportReqVO reqVo = new InfJobExportReqVO();
         InfJobExportReqVO reqVo = new InfJobExportReqVO();
         reqVo.setName("定时");
         reqVo.setName("定时");

+ 14 - 14
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java

@@ -59,19 +59,19 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个都是不匹配的数据
         // 下面几个都是不匹配的数据
         // userId 不同的
         // userId 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
         // userType
         // userType
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
         // applicationName 不同的
         // applicationName 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
         // requestUrl 不同的
         // requestUrl 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
         // 构造一个早期时间 2021-02-06 00:00:00
         // 构造一个早期时间 2021-02-06 00:00:00
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
         // duration 不同的
         // duration 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
         // resultCode 不同的
         // resultCode 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
 
 
         // 构造调用参数
         // 构造调用参数
         InfApiAccessLogPageReqVO reqVO = new InfApiAccessLogPageReqVO();
         InfApiAccessLogPageReqVO reqVO = new InfApiAccessLogPageReqVO();
@@ -117,19 +117,19 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个都是不匹配的数据
         // 下面几个都是不匹配的数据
         // userId 不同的
         // userId 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
         // userType
         // userType
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
         // applicationName 不同的
         // applicationName 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
         // requestUrl 不同的
         // requestUrl 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
         // 构造一个早期时间 2021-02-06 00:00:00
         // 构造一个早期时间 2021-02-06 00:00:00
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
         // duration 不同的
         // duration 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
         // resultCode 不同的
         // resultCode 不同的
-        infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
+        infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
 
 
         // 构造调用参数
         // 构造调用参数
         InfApiAccessLogExportReqVO reqVO = new InfApiAccessLogExportReqVO();
         InfApiAccessLogExportReqVO reqVO = new InfApiAccessLogExportReqVO();

+ 17 - 18
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java

@@ -1,16 +1,16 @@
 package cn.iocoder.yudao.adminserver.modules.infra.service.logger;
 package cn.iocoder.yudao.adminserver.modules.infra.service.logger;
 
 
 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
-import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
-import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
 import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
 import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
 import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
 import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiErrorLogMapper;
 import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiErrorLogMapper;
 import cn.iocoder.yudao.adminserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
 import cn.iocoder.yudao.adminserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
 import cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl.InfApiErrorLogServiceImpl;
 import cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl.InfApiErrorLogServiceImpl;
-import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
+import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Import;
 
 
@@ -20,11 +20,10 @@ import java.util.List;
 
 
 import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND;
 import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND;
 import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED;
 import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 
 /**
 /**
  * {@link InfApiErrorLogServiceImpl} 单元测试
  * {@link InfApiErrorLogServiceImpl} 单元测试
@@ -60,17 +59,17 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个都是不匹配的数据
         // 下面几个都是不匹配的数据
         // userId 不同的
         // userId 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
         // userType
         // userType
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
         // applicationName 不同的
         // applicationName 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
         // requestUrl 不同的
         // requestUrl 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
         // 构造一个早期时间 2021-02-06 00:00:00
         // 构造一个早期时间 2021-02-06 00:00:00
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
         // progressStatus 不同的
         // progressStatus 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
 
 
         // 构造调用参数
         // 构造调用参数
         InfApiErrorLogPageReqVO reqVO = new InfApiErrorLogPageReqVO();
         InfApiErrorLogPageReqVO reqVO = new InfApiErrorLogPageReqVO();
@@ -113,17 +112,17 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个都是不匹配的数据
         // 下面几个都是不匹配的数据
         // userId 不同的
         // userId 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
         // userType
         // userType
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
         // applicationName 不同的
         // applicationName 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
         // requestUrl 不同的
         // requestUrl 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
         // 构造一个早期时间 2021-02-06 00:00:00
         // 构造一个早期时间 2021-02-06 00:00:00
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
         // progressStatus 不同的
         // progressStatus 不同的
-        infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
+        infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
 
 
         // 构造调用参数
         // 构造调用参数
         InfApiErrorLogExportReqVO reqVO = new InfApiErrorLogExportReqVO();
         InfApiErrorLogExportReqVO reqVO = new InfApiErrorLogExportReqVO();

+ 11 - 3
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java

@@ -6,16 +6,18 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeE
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl;
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl;
 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
+import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
-import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
 import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
 import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Import;
@@ -66,7 +68,14 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
     @MockBean
     @MockBean
     private SysUserSessionCoreService userSessionCoreService;
     private SysUserSessionCoreService userSessionCoreService;
     @MockBean
     @MockBean
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
+    @MockBean
+    private SysPostService postService;
+
+    @BeforeEach
+    public void setUp() {
+        when(captchaService.isCaptchaEnable()).thenReturn(true);
+    }
 
 
     @Test
     @Test
     public void testLoadUserByUsername_success() {
     public void testLoadUserByUsername_success() {
@@ -80,7 +89,6 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
         LoginUser loginUser = (LoginUser) authService.loadUserByUsername(username);
         LoginUser loginUser = (LoginUser) authService.loadUserByUsername(username);
         // 校验
         // 校验
         AssertUtils.assertPojoEquals(user, loginUser, "updateTime");
         AssertUtils.assertPojoEquals(user, loginUser, "updateTime");
-        assertNull(loginUser.getRoleIds()); // 此时不会加载角色,所以是空的
     }
     }
 
 
     @Test
     @Test

+ 2 - 2
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java

@@ -73,12 +73,12 @@ public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
         });
         });
         userSessionMapper.insert(dbSession);
         userSessionMapper.insert(dbSession);
         // 测试 username 不匹配
         // 测试 username 不匹配
-        userSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {
+        userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> {
             o.setId(randomString());
             o.setId(randomString());
             o.setUserId(123456L);
             o.setUserId(123456L);
         }));
         }));
         // 测试 userIp 不匹配
         // 测试 userIp 不匹配
-        userSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {
+        userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> {
             o.setId(randomString());
             o.setId(randomString());
             o.setUserIp("testUserIp");
             o.setUserIp("testUserIp");
         }));
         }));

+ 2 - 2
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java

@@ -83,9 +83,9 @@ class SysDeptServiceTest extends BaseDbUnitTest {
         });
         });
         deptMapper.insert(dept);
         deptMapper.insert(dept);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        deptMapper.insert(ObjectUtils.clone(dept, o -> o.setName("发")));
+        deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setName("发")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        deptMapper.insert(ObjectUtils.clone(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 准备参数
         // 准备参数
         SysDeptListReqVO reqVO = new SysDeptListReqVO();
         SysDeptListReqVO reqVO = new SysDeptListReqVO();
         reqVO.setName("开");
         reqVO.setName("开");

+ 4 - 4
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java

@@ -49,9 +49,9 @@ class SysPostServiceTest extends BaseDbUnitTest {
         });
         });
         postMapper.insert(postDO);
         postMapper.insert(postDO);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        postMapper.insert(ObjectUtils.clone(postDO, o -> o.setName("程序员")));
+        postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setName("程序员")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        postMapper.insert(ObjectUtils.clone(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
 
 
         // 准备参数
         // 准备参数
         SysPostPageReqVO reqVO = new SysPostPageReqVO();
         SysPostPageReqVO reqVO = new SysPostPageReqVO();
@@ -76,9 +76,9 @@ class SysPostServiceTest extends BaseDbUnitTest {
         });
         });
         postMapper.insert(postDO);
         postMapper.insert(postDO);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        postMapper.insert(ObjectUtils.clone(postDO, o -> o.setName("程序员")));
+        postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setName("程序员")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        postMapper.insert(ObjectUtils.clone(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 准备参数
         // 准备参数
         SysPostExportReqVO reqVO = new SysPostExportReqVO();
         SysPostExportReqVO reqVO = new SysPostExportReqVO();
         reqVO.setName("码");
         reqVO.setName("码");

+ 6 - 9
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataServiceTest.java

@@ -14,17 +14,14 @@ import cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict.SysDictDataP
 import cn.iocoder.yudao.adminserver.modules.system.service.dict.impl.SysDictDataServiceImpl;
 import cn.iocoder.yudao.adminserver.modules.system.service.dict.impl.SysDictDataServiceImpl;
 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
-import com.google.common.collect.ImmutableTable;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Import;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
-import java.util.Date;
 import java.util.List;
 import java.util.List;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 
 
-import static cn.hutool.core.bean.BeanUtil.getFieldValue;
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
@@ -61,11 +58,11 @@ public class SysDictDataServiceTest extends BaseDbUnitTest {
         });
         });
         dictDataMapper.insert(dbDictData);
         dictDataMapper.insert(dbDictData);
         // 测试 label 不匹配
         // 测试 label 不匹配
-        dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setLabel("艿")));
+        dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setLabel("艿")));
         // 测试 dictType 不匹配
         // 测试 dictType 不匹配
-        dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setDictType("nai")));
+        dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setDictType("nai")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 准备参数
         // 准备参数
         SysDictDataPageReqVO reqVO = new SysDictDataPageReqVO();
         SysDictDataPageReqVO reqVO = new SysDictDataPageReqVO();
         reqVO.setLabel("芋");
         reqVO.setLabel("芋");
@@ -90,11 +87,11 @@ public class SysDictDataServiceTest extends BaseDbUnitTest {
         });
         });
         dictDataMapper.insert(dbDictData);
         dictDataMapper.insert(dbDictData);
         // 测试 label 不匹配
         // 测试 label 不匹配
-        dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setLabel("艿")));
+        dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setLabel("艿")));
         // 测试 dictType 不匹配
         // 测试 dictType 不匹配
-        dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setDictType("nai")));
+        dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setDictType("nai")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 准备参数
         // 准备参数
         SysDictDataExportReqVO reqVO = new SysDictDataExportReqVO();
         SysDictDataExportReqVO reqVO = new SysDictDataExportReqVO();
         reqVO.setLabel("芋");
         reqVO.setLabel("芋");

+ 8 - 8
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeServiceTest.java

@@ -57,13 +57,13 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest {
        });
        });
        dictTypeMapper.insert(dbDictType);
        dictTypeMapper.insert(dbDictType);
        // 测试 name 不匹配
        // 测试 name 不匹配
-       dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setName("tudou")));
+       dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setName("tudou")));
        // 测试 type 不匹配
        // 测试 type 不匹配
-       dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setType("土豆")));
+       dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setType("土豆")));
        // 测试 status 不匹配
        // 测试 status 不匹配
-       dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+       dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
        // 测试 createTime 不匹配
        // 测试 createTime 不匹配
-       dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
+       dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
        // 准备参数
        // 准备参数
        SysDictTypePageReqVO reqVO = new SysDictTypePageReqVO();
        SysDictTypePageReqVO reqVO = new SysDictTypePageReqVO();
        reqVO.setName("nai");
        reqVO.setName("nai");
@@ -91,13 +91,13 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest {
         });
         });
         dictTypeMapper.insert(dbDictType);
         dictTypeMapper.insert(dbDictType);
         // 测试 name 不匹配
         // 测试 name 不匹配
-        dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setName("tudou")));
+        dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setName("tudou")));
         // 测试 type 不匹配
         // 测试 type 不匹配
-        dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setType("土豆")));
+        dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setType("土豆")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
+        dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
         // 准备参数
         // 准备参数
         SysDictTypeExportReqVO reqVO = new SysDictTypeExportReqVO();
         SysDictTypeExportReqVO reqVO = new SysDictTypeExportReqVO();
         reqVO.setName("nai");
         reqVO.setName("nai");

+ 5 - 5
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeServiceTest.java

@@ -131,15 +131,15 @@ public class SysErrorCodeServiceTest extends BaseDbUnitTest {
         });
         });
         errorCodeMapper.insert(dbErrorCode);
         errorCodeMapper.insert(dbErrorCode);
         // 测试 type 不匹配
         // 测试 type 不匹配
-        errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType())));
+        errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType())));
         // 测试 applicationName 不匹配
         // 测试 applicationName 不匹配
-        errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setApplicationName("yunai")));
+        errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setApplicationName("yunai")));
         // 测试 code 不匹配
         // 测试 code 不匹配
-        errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setCode(2)));
+        errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setCode(2)));
         // 测试 message 不匹配
         // 测试 message 不匹配
-        errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setMessage("nai")));
+        errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setMessage("nai")));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setCreateTime(buildTime(2020, 12, 12))));
+        errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setCreateTime(buildTime(2020, 12, 12))));
         return dbErrorCode;
         return dbErrorCode;
     }
     }
 
 

+ 8 - 8
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java

@@ -51,13 +51,13 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个都是不匹配的数据
         // 下面几个都是不匹配的数据
         // 登录失败的
         // 登录失败的
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
         // 不同ip段的
         // 不同ip段的
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
         // 不同username
         // 不同username
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai")));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUsername("yunai")));
         // 构造一个早期时间 2021-02-06 00:00:00
         // 构造一个早期时间 2021-02-06 00:00:00
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
 
 
 
 
         // 构造调用参数
         // 构造调用参数
@@ -96,13 +96,13 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个都是不匹配的数据
         // 下面几个都是不匹配的数据
         // 登录失败的
         // 登录失败的
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
         // 不同ip段的
         // 不同ip段的
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
         // 不同username
         // 不同username
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai")));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUsername("yunai")));
         // 构造一个早期时间 2021-02-06 00:00:00
         // 构造一个早期时间 2021-02-06 00:00:00
-        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
+        loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
 
 
 
 
         // 构造调用参数
         // 构造调用参数

+ 10 - 10
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogServiceImplTest.java

@@ -87,15 +87,15 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个是不匹配的数据
         // 下面几个是不匹配的数据
         // 随机 userId
         // 随机 userId
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
         // module 不同
         // module 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user")));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setModule("user")));
         // type 不同
         // type 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
         // createTime 不同
         // createTime 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
         // resultCode 不同
         // resultCode 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
 
 
         // 构造调用参数
         // 构造调用参数
         SysOperateLogPageReqVO reqVO = new SysOperateLogPageReqVO();
         SysOperateLogPageReqVO reqVO = new SysOperateLogPageReqVO();
@@ -138,15 +138,15 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest {
 
 
         // 下面几个是不匹配的数据
         // 下面几个是不匹配的数据
         // 随机 userId
         // 随机 userId
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
         // module 不同
         // module 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user")));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setModule("user")));
         // type 不同
         // type 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
         // createTime 不同
         // createTime 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
         // resultCode 不同
         // resultCode 不同
-        operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
+        operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
 
 
         // 构造调用参数
         // 构造调用参数
         SysOperateLogExportReqVO reqVO = new SysOperateLogExportReqVO();
         SysOperateLogExportReqVO reqVO = new SysOperateLogExportReqVO();

+ 2 - 2
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java

@@ -46,9 +46,9 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest {
         sysNoticeMapper.insert(dbNotice);
         sysNoticeMapper.insert(dbNotice);
 
 
         // 测试 title 不匹配
         // 测试 title 不匹配
-        sysNoticeMapper.insert(ObjectUtils.clone(dbNotice, o -> o.setTitle("尼古拉斯凯奇也来啦!")));
+        sysNoticeMapper.insert(ObjectUtils.cloneIgnoreId(dbNotice, o -> o.setTitle("尼古拉斯凯奇也来啦!")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        sysNoticeMapper.insert(ObjectUtils.clone(dbNotice, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        sysNoticeMapper.insert(ObjectUtils.cloneIgnoreId(dbNotice, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
 
 
 
 
         // 查询
         // 查询

+ 121 - 1
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java

@@ -1,12 +1,19 @@
 package cn.iocoder.yudao.adminserver.modules.system.service.permission;
 package cn.iocoder.yudao.adminserver.modules.system.service.permission;
 
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
+import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.impl.SysPermissionServiceImpl;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.impl.SysPermissionServiceImpl;
+import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Import;
@@ -17,8 +24,12 @@ import java.util.List;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static java.util.Collections.singletonList;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 
 @Import(SysPermissionServiceImpl.class)
 @Import(SysPermissionServiceImpl.class)
 public class SysPermissionServiceTest extends BaseDbUnitTest {
 public class SysPermissionServiceTest extends BaseDbUnitTest {
@@ -35,6 +46,8 @@ public class SysPermissionServiceTest extends BaseDbUnitTest {
     private SysRoleService roleService;
     private SysRoleService roleService;
     @MockBean
     @MockBean
     private SysMenuService menuService;
     private SysMenuService menuService;
+    @MockBean
+    private SysDeptService deptService;
 
 
     @MockBean
     @MockBean
     private SysPermissionProducer permissionProducer;
     private SysPermissionProducer permissionProducer;
@@ -106,4 +119,111 @@ public class SysPermissionServiceTest extends BaseDbUnitTest {
         assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
         assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
     }
     }
 
 
+    @Test // 测试从 context 获取的场景
+    public void testGetDeptDataPermission_fromContext() {
+        // 准备参数
+        LoginUser loginUser = randomPojo(LoginUser.class);
+        // mock 方法
+        DeptDataPermissionRespDTO respDTO = new DeptDataPermissionRespDTO();
+        loginUser.setContext(SysPermissionServiceImpl.CONTEXT_KEY, respDTO);
+
+        // 调用
+        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+        // 断言
+        assertSame(respDTO, result);
+    }
+
+    @Test
+    public void testGetDeptDataPermission_All() {
+        // 准备参数
+        LoginUser loginUser = randomPojo(LoginUser.class);
+        // mock 方法
+        SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope()));
+        when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+
+        // 调用
+        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+        // 断言
+        assertTrue(result.getAll());
+        assertFalse(result.getSelf());
+        assertTrue(CollUtil.isEmpty(result.getDeptIds()));
+        assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+    }
+
+    @Test
+    public void testGetDeptDataPermission_DeptCustom() {
+        // 准备参数
+        LoginUser loginUser = randomPojo(LoginUser.class);
+        // mock 方法
+        SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope()));
+        when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+
+        // 调用
+        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+        // 断言
+        assertFalse(result.getAll());
+        assertFalse(result.getSelf());
+        assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size());
+        assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds()));
+        assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
+        assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+    }
+
+    @Test
+    public void testGetDeptDataPermission_DeptOnly() {
+        // 准备参数
+        LoginUser loginUser = randomPojo(LoginUser.class);
+        // mock 方法
+        SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope()));
+        when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+
+        // 调用
+        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+        // 断言
+        assertFalse(result.getAll());
+        assertFalse(result.getSelf());
+        assertEquals(1, result.getDeptIds().size());
+        assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
+        assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+    }
+
+    @Test
+    public void testGetDeptDataPermission_DeptAndChild() {
+        // 准备参数
+        LoginUser loginUser = randomPojo(LoginUser.class);
+        // mock 方法(角色)
+        SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope()));
+        when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+        // mock 方法(部门)
+        SysDeptDO deptDO = randomPojo(SysDeptDO.class);
+        when(deptService.getDeptsByParentIdFromCache(eq(loginUser.getDeptId()), eq(true)))
+                .thenReturn(singletonList(deptDO));
+
+        // 调用
+        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+        // 断言
+        assertFalse(result.getAll());
+        assertFalse(result.getSelf());
+        assertEquals(1, result.getDeptIds().size());
+        assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId()));
+        assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+    }
+
+    @Test
+    public void testGetDeptDataPermission_Self() {
+        // 准备参数
+        LoginUser loginUser = randomPojo(LoginUser.class);
+        // mock 方法
+        SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope()));
+        when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
+
+        // 调用
+        DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
+        // 断言
+        assertFalse(result.getAll());
+        assertTrue(result.getSelf());
+        assertTrue(CollUtil.isEmpty(result.getDeptIds()));
+        assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
+    }
+
 }
 }

+ 4 - 4
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleServiceTest.java

@@ -133,11 +133,11 @@ public class SysRoleServiceTest extends BaseDbUnitTest {
 
 
         //调用
         //调用
         Set<Long> deptIdSet = Arrays.asList(1L, 2L, 3L, 4L, 5L).stream().collect(Collectors.toSet());
         Set<Long> deptIdSet = Arrays.asList(1L, 2L, 3L, 4L, 5L).stream().collect(Collectors.toSet());
-        sysRoleService.updateRoleDataScope(roleId, DataScopeEnum.DEPT_CUSTOM.getScore(), deptIdSet);
+        sysRoleService.updateRoleDataScope(roleId, DataScopeEnum.DEPT_CUSTOM.getScope(), deptIdSet);
 
 
         //断言
         //断言
         SysRoleDO newRoleDO = roleMapper.selectById(roleId);
         SysRoleDO newRoleDO = roleMapper.selectById(roleId);
-        assertEquals(DataScopeEnum.DEPT_CUSTOM.getScore(), newRoleDO.getDataScope());
+        assertEquals(DataScopeEnum.DEPT_CUSTOM.getScope(), newRoleDO.getDataScope());
 
 
         Set<Long> newDeptIdSet = newRoleDO.getDataScopeDeptIds();
         Set<Long> newDeptIdSet = newRoleDO.getDataScopeDeptIds();
         assertTrue(deptIdSet.size() == newDeptIdSet.size());
         assertTrue(deptIdSet.size() == newDeptIdSet.size());
@@ -242,7 +242,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest {
             o.setCode("code");
             o.setCode("code");
             o.setType(SysRoleTypeEnum.CUSTOM.getType());
             o.setType(SysRoleTypeEnum.CUSTOM.getType());
             o.setStatus(1);
             o.setStatus(1);
-            o.setDataScope(DataScopeEnum.ALL.getScore());
+            o.setDataScope(DataScopeEnum.ALL.getScope());
         });
         });
         roleMapper.insert(roleDO);
         roleMapper.insert(roleDO);
 
 
@@ -293,7 +293,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest {
             o.setName(name);
             o.setName(name);
             o.setType(typeEnum.getType());
             o.setType(typeEnum.getType());
             o.setStatus(status);
             o.setStatus(status);
-            o.setDataScope(scopeEnum.getScore());
+            o.setDataScope(scopeEnum.getScope());
             o.setCode(code);
             o.setCode(code);
         });
         });
         return roleDO;
         return roleDO;

+ 3 - 3
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelServiceTest.java

@@ -169,11 +169,11 @@ public class SysSmsChannelServiceTest extends BaseDbUnitTest {
        });
        });
        smsChannelMapper.insert(dbSmsChannel);
        smsChannelMapper.insert(dbSmsChannel);
        // 测试 signature 不匹配
        // 测试 signature 不匹配
-       smsChannelMapper.insert(ObjectUtils.clone(dbSmsChannel, o -> o.setSignature("源码")));
+       smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码")));
        // 测试 status 不匹配
        // 测试 status 不匹配
-       smsChannelMapper.insert(ObjectUtils.clone(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+       smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
        // 测试 createTime 不匹配
        // 测试 createTime 不匹配
-       smsChannelMapper.insert(ObjectUtils.clone(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11))));
+       smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11))));
        // 准备参数
        // 准备参数
        SysSmsChannelPageReqVO reqVO = new SysSmsChannelPageReqVO();
        SysSmsChannelPageReqVO reqVO = new SysSmsChannelPageReqVO();
        reqVO.setSignature("芋道");
        reqVO.setSignature("芋道");

+ 14 - 14
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogServiceTest.java

@@ -57,19 +57,19 @@ public class SysSmsLogServiceTest extends BaseDbUnitTest {
        });
        });
        smsLogMapper.insert(dbSmsLog);
        smsLogMapper.insert(dbSmsLog);
        // 测试 channelId 不匹配
        // 测试 channelId 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setChannelId(2L)));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L)));
        // 测试 templateId 不匹配
        // 测试 templateId 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setTemplateId(20L)));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L)));
        // 测试 mobile 不匹配
        // 测试 mobile 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setMobile("18818260999")));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999")));
        // 测试 sendStatus 不匹配
        // 测试 sendStatus 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
        // 测试 sendTime 不匹配
        // 测试 sendTime 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
        // 测试 receiveStatus 不匹配
        // 测试 receiveStatus 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
        // 测试 receiveTime 不匹配
        // 测试 receiveTime 不匹配
-       smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
+       smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
        // 准备参数
        // 准备参数
        SysSmsLogPageReqVO reqVO = new SysSmsLogPageReqVO();
        SysSmsLogPageReqVO reqVO = new SysSmsLogPageReqVO();
        reqVO.setChannelId(1L);
        reqVO.setChannelId(1L);
@@ -104,19 +104,19 @@ public class SysSmsLogServiceTest extends BaseDbUnitTest {
         });
         });
         smsLogMapper.insert(dbSmsLog);
         smsLogMapper.insert(dbSmsLog);
         // 测试 channelId 不匹配
         // 测试 channelId 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setChannelId(2L)));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L)));
         // 测试 templateId 不匹配
         // 测试 templateId 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setTemplateId(20L)));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L)));
         // 测试 mobile 不匹配
         // 测试 mobile 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setMobile("18818260999")));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999")));
         // 测试 sendStatus 不匹配
         // 测试 sendStatus 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
         // 测试 sendTime 不匹配
         // 测试 sendTime 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
         // 测试 receiveStatus 不匹配
         // 测试 receiveStatus 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
         // 测试 receiveTime 不匹配
         // 测试 receiveTime 不匹配
-        smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
+        smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
         // 准备参数
         // 准备参数
         SysSmsLogExportReqVO reqVO = new SysSmsLogExportReqVO();
         SysSmsLogExportReqVO reqVO = new SysSmsLogExportReqVO();
         reqVO.setChannelId(1L);
         reqVO.setChannelId(1L);

+ 14 - 14
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateServiceTest.java

@@ -190,19 +190,19 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
        });
        });
        smsTemplateMapper.insert(dbSmsTemplate);
        smsTemplateMapper.insert(dbSmsTemplate);
        // 测试 type 不匹配
        // 测试 type 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
        // 测试 status 不匹配
        // 测试 status 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
        // 测试 code 不匹配
        // 测试 code 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCode("yuanma")));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
        // 测试 content 不匹配
        // 测试 content 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setContent("源码")));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
        // 测试 apiTemplateId 不匹配
        // 测试 apiTemplateId 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
        // 测试 channelId 不匹配
        // 测试 channelId 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setChannelId(2L)));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
        // 测试 createTime 不匹配
        // 测试 createTime 不匹配
-       smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
+       smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
        // 准备参数
        // 准备参数
        SysSmsTemplatePageReqVO reqVO = new SysSmsTemplatePageReqVO();
        SysSmsTemplatePageReqVO reqVO = new SysSmsTemplatePageReqVO();
        reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType());
        reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType());
@@ -236,19 +236,19 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
         });
         });
         smsTemplateMapper.insert(dbSmsTemplate);
         smsTemplateMapper.insert(dbSmsTemplate);
         // 测试 type 不匹配
         // 测试 type 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 测试 code 不匹配
         // 测试 code 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCode("yuanma")));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
         // 测试 content 不匹配
         // 测试 content 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setContent("源码")));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
         // 测试 apiTemplateId 不匹配
         // 测试 apiTemplateId 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
         // 测试 channelId 不匹配
         // 测试 channelId 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setChannelId(2L)));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
+        smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
         // 准备参数
         // 准备参数
         SysSmsTemplateExportReqVO reqVO = new SysSmsTemplateExportReqVO();
         SysSmsTemplateExportReqVO reqVO = new SysSmsTemplateExportReqVO();
         reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType());
         reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType());

+ 181 - 0
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java

@@ -0,0 +1,181 @@
+package cn.iocoder.yudao.adminserver.modules.system.service.tenant;
+
+import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper;
+import cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl.SysTenantServiceImpl;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * {@link SysTenantServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+@Import(SysTenantServiceImpl.class)
+public class SysTenantServiceTest extends BaseDbUnitTest {
+
+    @Resource
+    private SysTenantServiceImpl tenantService;
+
+    @Resource
+    private SysTenantMapper tenantMapper;
+
+    @Test
+    public void testCreateTenant_success() {
+        // 准备参数
+        SysTenantCreateReqVO reqVO = randomPojo(SysTenantCreateReqVO.class, o -> o.setStatus(randomCommonStatus()));
+
+        // 调用
+        Long tenantId = tenantService.createTenant(reqVO);
+        // 断言
+        assertNotNull(tenantId);
+        // 校验记录的属性是否正确
+        SysTenantDO tenant = tenantMapper.selectById(tenantId);
+        assertPojoEquals(reqVO, tenant);
+    }
+
+    @Test
+    public void testUpdateTenant_success() {
+        // mock 数据
+        SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> o.setStatus(randomCommonStatus()));
+        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        SysTenantUpdateReqVO reqVO = randomPojo(SysTenantUpdateReqVO.class, o -> {
+            o.setId(dbTenant.getId()); // 设置更新的 ID
+            o.setStatus(randomCommonStatus());
+        });
+
+        // 调用
+        tenantService.updateTenant(reqVO);
+        // 校验是否更新正确
+        SysTenantDO tenant = tenantMapper.selectById(reqVO.getId()); // 获取最新的
+        assertPojoEquals(reqVO, tenant);
+    }
+
+    @Test
+    public void testUpdateTenant_notExists() {
+        // 准备参数
+        SysTenantUpdateReqVO reqVO = randomPojo(SysTenantUpdateReqVO.class);
+
+        // 调用, 并断言异常
+        assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_NOT_EXISTS);
+    }
+
+    @Test
+    public void testDeleteTenant_success() {
+        // mock 数据
+        SysTenantDO dbTenant = randomPojo(SysTenantDO.class,
+                o -> o.setStatus(randomCommonStatus()));
+        tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        Long id = dbTenant.getId();
+
+        // 调用
+        tenantService.deleteTenant(id);
+        // 校验数据不存在了
+        assertNull(tenantMapper.selectById(id));
+    }
+
+    @Test
+    public void testDeleteTenant_notExists() {
+        // 准备参数
+        Long id = randomLongId();
+
+        // 调用, 并断言异常
+        assertServiceException(() -> tenantService.deleteTenant(id), TENANT_NOT_EXISTS);
+    }
+
+    @Test
+    public void testGetTenantPage() {
+        // mock 数据
+        SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> { // 等会查询到
+            o.setName("芋道源码");
+            o.setContactName("芋艿");
+            o.setContactMobile("15601691300");
+            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
+            o.setCreateTime(buildTime(2020, 12, 12));
+        });
+        tenantMapper.insert(dbTenant);
+        // 测试 name 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setName(randomString())));
+        // 测试 contactName 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactName(randomString())));
+        // 测试 contactMobile 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactMobile(randomString())));
+        // 测试 status 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        // 测试 createTime 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12))));
+        // 准备参数
+        SysTenantPageReqVO reqVO = new SysTenantPageReqVO();
+        reqVO.setName("芋道");
+        reqVO.setContactName("艿");
+        reqVO.setContactMobile("1560");
+        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        reqVO.setBeginCreateTime(buildTime(2020, 12, 1));
+        reqVO.setEndCreateTime(buildTime(2020, 12, 24));
+
+        // 调用
+        PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(reqVO);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbTenant, pageResult.getList().get(0));
+    }
+
+    @Test
+    public void testGetTenantList() {
+        // mock 数据
+        SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> { // 等会查询到
+            o.setName("芋道源码");
+            o.setContactName("芋艿");
+            o.setContactMobile("15601691300");
+            o.setStatus(CommonStatusEnum.ENABLE.getStatus());
+            o.setCreateTime(buildTime(2020, 12, 12));
+        });
+        tenantMapper.insert(dbTenant);
+        // 测试 name 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setName(randomString())));
+        // 测试 contactName 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactName(randomString())));
+        // 测试 contactMobile 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactMobile(randomString())));
+        // 测试 status 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        // 测试 createTime 不匹配
+        tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12))));
+        // 准备参数
+        SysTenantExportReqVO reqVO = new SysTenantExportReqVO();
+        reqVO.setName("芋道");
+        reqVO.setContactName("艿");
+        reqVO.setContactMobile("1560");
+        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        reqVO.setBeginCreateTime(buildTime(2020, 12, 1));
+        reqVO.setEndCreateTime(buildTime(2020, 12, 24));
+
+        // 调用
+        List<SysTenantDO> list = tenantService.getTenantList(reqVO);
+        // 断言
+        assertEquals(1, list.size());
+        assertPojoEquals(dbTenant, list.get(0));
+    }
+
+}

+ 5 - 5
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java

@@ -309,15 +309,15 @@ public class SysUserServiceImplTest extends BaseDbUnitTest {
         });
         });
         userMapper.insert(dbUser);
         userMapper.insert(dbUser);
         // 测试 username 不匹配
         // 测试 username 不匹配
-        userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setUsername("yuanma")));
+        userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setUsername("yuanma")));
         // 测试 mobile 不匹配
         // 测试 mobile 不匹配
-        userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setMobile("18818260888")));
+        userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setMobile("18818260888")));
         // 测试 status 不匹配
         // 测试 status 不匹配
-        userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
+        userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
         // 测试 createTime 不匹配
         // 测试 createTime 不匹配
-        userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11))));
+        userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11))));
         // 测试 dept 不匹配
         // 测试 dept 不匹配
-        userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setDeptId(0L)));
+        userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setDeptId(0L)));
         return dbUser;
         return dbUser;
     }
     }
 
 

+ 1 - 0
yudao-admin-server/src/test/resources/sql/clean.sql

@@ -24,3 +24,4 @@ DELETE FROM "sys_sms_template";
 DELETE FROM "sys_sms_log";
 DELETE FROM "sys_sms_log";
 DELETE FROM "sys_error_code";
 DELETE FROM "sys_error_code";
 DELETE FROM "sys_social_user";
 DELETE FROM "sys_social_user";
+DELETE FROM "sys_tenant";

+ 26 - 3
yudao-admin-server/src/test/resources/sql/create_tables.sql

@@ -1,7 +1,7 @@
 -- inf 开头的 DB
 -- inf 开头的 DB
 
 
 CREATE TABLE IF NOT EXISTS "inf_config" (
 CREATE TABLE IF NOT EXISTS "inf_config" (
-    "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
     "group" varchar(50) NOT NULL,
     "group" varchar(50) NOT NULL,
     "type" tinyint NOT NULL,
     "type" tinyint NOT NULL,
     "name" varchar(100) NOT NULL DEFAULT '',
     "name" varchar(100) NOT NULL DEFAULT '',
@@ -26,6 +26,7 @@ CREATE TABLE IF NOT EXISTS "inf_file" (
     "updater" varchar(64) DEFAULT '',
     "updater" varchar(64) DEFAULT '',
     "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "deleted" bit NOT NULL DEFAULT FALSE,
     "deleted" bit NOT NULL DEFAULT FALSE,
+    "tenant_id" bigint not null default  '0',
     PRIMARY KEY ("id")
     PRIMARY KEY ("id")
 ) COMMENT '文件表';
 ) COMMENT '文件表';
 
 
@@ -82,6 +83,7 @@ CREATE TABLE IF NOT EXISTS "sys_dept" (
     "updater" varchar(64) DEFAULT '',
     "updater" varchar(64) DEFAULT '',
     "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "deleted" bit NOT NULL DEFAULT FALSE,
     "deleted" bit NOT NULL DEFAULT FALSE,
+    "tenant_id" bigint not null default  '0',
     PRIMARY KEY ("id")
     PRIMARY KEY ("id")
 ) COMMENT '部门表';
 ) COMMENT '部门表';
 
 
@@ -189,6 +191,7 @@ CREATE TABLE IF NOT EXISTS `sys_user_session` (
     `updater` varchar(64) DEFAULT '' ,
     `updater` varchar(64) DEFAULT '' ,
     "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "deleted" bit NOT NULL DEFAULT FALSE,
     "deleted" bit NOT NULL DEFAULT FALSE,
+    "tenant_id" bigint not null default  '0',
     PRIMARY KEY (`id`)
     PRIMARY KEY (`id`)
 ) COMMENT '用户在线 Session';
 ) COMMENT '用户在线 Session';
 
 
@@ -204,6 +207,7 @@ CREATE TABLE IF NOT EXISTS "sys_post" (
     "updater"     varchar(64)          DEFAULT '',
     "updater"     varchar(64)          DEFAULT '',
     "update_time" timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "update_time" timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "deleted"     bit         NOT NULL DEFAULT FALSE,
     "deleted"     bit         NOT NULL DEFAULT FALSE,
+    "tenant_id" bigint not null default  '0',
     PRIMARY KEY ("id")
     PRIMARY KEY ("id")
 ) COMMENT '岗位信息表';
 ) COMMENT '岗位信息表';
 
 
@@ -218,7 +222,8 @@ CREATE TABLE IF NOT EXISTS "sys_notice" (
 	"updater" varchar(64) DEFAULT '' COMMENT '更新者',
 	"updater" varchar(64) DEFAULT '' COMMENT '更新者',
 	"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
 	"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
 	"deleted" bit NOT NULL DEFAULT 0 COMMENT '是否删除',
 	"deleted" bit NOT NULL DEFAULT 0 COMMENT '是否删除',
-	PRIMARY KEY("id")
+    "tenant_id" bigint not null default  '0',
+    PRIMARY KEY("id")
 ) COMMENT '通知公告表';
 ) COMMENT '通知公告表';
 
 
 CREATE TABLE IF NOT EXISTS `sys_login_log` (
 CREATE TABLE IF NOT EXISTS `sys_login_log` (
@@ -264,6 +269,7 @@ CREATE TABLE IF NOT EXISTS `sys_operate_log` (
     `updater`        varchar(64)            DEFAULT '',
     `updater`        varchar(64)            DEFAULT '',
     `update_time`      datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     `update_time`      datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     `deleted`          bit(1)        NOT NULL DEFAULT '0',
     `deleted`          bit(1)        NOT NULL DEFAULT '0',
+    "tenant_id"         bigint not null default  '0',
     PRIMARY KEY (`id`)
     PRIMARY KEY (`id`)
 ) COMMENT ='操作日志记录';
 ) COMMENT ='操作日志记录';
 
 
@@ -287,6 +293,7 @@ CREATE TABLE IF NOT EXISTS "sys_user" (
     "updater" varchar(64) default '',
     "updater" varchar(64) default '',
     "update_time" timestamp not null default current_timestamp,
     "update_time" timestamp not null default current_timestamp,
     "deleted" bit not null default false,
     "deleted" bit not null default false,
+    "tenant_id" bigint not null default  '0',
     primary key ("id")
     primary key ("id")
 ) comment '用户信息表';
 ) comment '用户信息表';
 
 
@@ -311,11 +318,12 @@ CREATE TABLE IF NOT EXISTS "inf_api_access_log" (
   "updater" varchar(64) default '',
   "updater" varchar(64) default '',
   "update_time" timestamp not null default current_timestamp,
   "update_time" timestamp not null default current_timestamp,
   "deleted" bit not null default false,
   "deleted" bit not null default false,
+  "tenant_id" bigint not null default  '0',
   primary key ("id")
   primary key ("id")
 ) COMMENT 'API 访问日志表';
 ) COMMENT 'API 访问日志表';
 
 
 CREATE TABLE IF NOT EXISTS "inf_api_error_log" (
 CREATE TABLE IF NOT EXISTS "inf_api_error_log" (
- "id" integer not null GENERATED BY DEFAULT AS IDENTITY,
+ "id" bigint not null GENERATED BY DEFAULT AS IDENTITY,
  "trace_id" varchar(64) not null,
  "trace_id" varchar(64) not null,
  "user_id" bigint not null default '0',
  "user_id" bigint not null default '0',
  "user_type" tinyint not null default '0',
  "user_type" tinyint not null default '0',
@@ -342,6 +350,7 @@ CREATE TABLE IF NOT EXISTS "inf_api_error_log" (
  "updater" varchar(64) default '',
  "updater" varchar(64) default '',
  "update_time" timestamp not null default current_timestamp,
  "update_time" timestamp not null default current_timestamp,
  "deleted" bit not null default false,
  "deleted" bit not null default false,
+ "tenant_id" bigint not null default  '0',
  primary key ("id")
  primary key ("id")
 ) COMMENT '系统异常日志';
 ) COMMENT '系统异常日志';
 
 
@@ -449,3 +458,17 @@ CREATE TABLE IF NOT EXISTS "sys_social_user" (
    "deleted" bit NOT NULL DEFAULT FALSE,
    "deleted" bit NOT NULL DEFAULT FALSE,
    PRIMARY KEY ("id")
    PRIMARY KEY ("id")
 ) COMMENT '社交用户';
 ) COMMENT '社交用户';
+
+CREATE TABLE IF NOT EXISTS "sys_tenant" (
+    "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "name" varchar(63) NOT NULL,
+    "contact_name" varchar(255) NOT NULL,
+    "contact_mobile" varchar(255),
+    "status" tinyint NOT NULL,
+    "creator" varchar(64) DEFAULT '',
+    "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updater" varchar(64) DEFAULT '',
+    "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "deleted" bit NOT NULL DEFAULT FALSE,
+    PRIMARY KEY ("id")
+) COMMENT '租户';

+ 65 - 0
yudao-admin-ui/src/api/system/tenant.js

@@ -0,0 +1,65 @@
+import request from '@/utils/request'
+
+// 使用租户名,获得租户编号
+export function getTenantIdByName(name) {
+  return request({
+    url: '/system/tenant/get-id-by-name',
+    method: 'get',
+    params: {
+      name
+    }
+  })
+}
+
+// 创建租户
+export function createTenant(data) {
+  return request({
+    url: '/system/tenant/create',
+    method: 'post',
+    data: data
+  })
+}
+
+// 更新租户
+export function updateTenant(data) {
+  return request({
+    url: '/system/tenant/update',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除租户
+export function deleteTenant(id) {
+  return request({
+    url: '/system/tenant/delete?id=' + id,
+    method: 'delete'
+  })
+}
+
+// 获得租户
+export function getTenant(id) {
+  return request({
+    url: '/system/tenant/get?id=' + id,
+    method: 'get'
+  })
+}
+
+// 获得租户分页
+export function getTenantPage(query) {
+  return request({
+    url: '/system/tenant/page',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出租户 Excel
+export function exportTenantExcel(query) {
+  return request({
+    url: '/system/tenant/export-excel',
+    method: 'get',
+    params: query,
+    responseType: 'blob'
+  })
+}

+ 6 - 0
yudao-admin-ui/src/utils/request.js

@@ -3,6 +3,7 @@ import { Notification, MessageBox, Message } from 'element-ui'
 import store from '@/store'
 import store from '@/store'
 import { getToken } from '@/utils/auth'
 import { getToken } from '@/utils/auth'
 import errorCode from '@/utils/errorCode'
 import errorCode from '@/utils/errorCode'
+import Cookies from "js-cookie";
 
 
 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
 // 创建axios实例
 // 创建axios实例
@@ -19,6 +20,11 @@ service.interceptors.request.use(config => {
   if (getToken() && !isToken) {
   if (getToken() && !isToken) {
     config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
     config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
   }
   }
+  // 设置租户
+  const tenantId = Cookies.get('tenantId');
+  if (tenantId) {
+    config.headers['tenant-id'] = tenantId;
+  }
   // get请求映射params参数
   // get请求映射params参数
   if (config.method === 'get' && config.params) {
   if (config.method === 'get' && config.params) {
     let url = config.url + '?';
     let url = config.url + '?';

+ 35 - 3
yudao-admin-ui/src/views/login.vue

@@ -2,6 +2,11 @@
   <div class="login">
   <div class="login">
     <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
     <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
       <h3 class="title">芋道后台管理系统</h3>
       <h3 class="title">芋道后台管理系统</h3>
+      <el-form-item prop="tenantName">
+        <el-input v-model="loginForm.tenantName" type="text" auto-complete="off" placeholder='租户'>
+          <svg-icon slot="prefix" icon-class="tree" class="el-input__icon input-icon" />
+        </el-input>
+      </el-form-item>
       <el-form-item prop="username">
       <el-form-item prop="username">
         <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
         <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
           <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
           <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
@@ -46,6 +51,7 @@
 
 
 <script>
 <script>
 import { getCodeImg,socialAuthRedirect } from "@/api/login";
 import { getCodeImg,socialAuthRedirect } from "@/api/login";
+import { getTenantIdByName } from "@/api/system/tenant";
 import Cookies from "js-cookie";
 import Cookies from "js-cookie";
 import { encrypt, decrypt } from '@/utils/jsencrypt'
 import { encrypt, decrypt } from '@/utils/jsencrypt'
 import {InfApiErrorLogProcessStatusEnum, SysUserSocialTypeEnum} from "@/utils/constants";
 import {InfApiErrorLogProcessStatusEnum, SysUserSocialTypeEnum} from "@/utils/constants";
@@ -60,9 +66,29 @@ export default {
         password: "admin123",
         password: "admin123",
         rememberMe: false,
         rememberMe: false,
         code: "",
         code: "",
-        uuid: ""
+        uuid: "",
+        tenantName: "芋道源码",
       },
       },
       loginRules: {
       loginRules: {
+        tenantName: [
+          { required: true, trigger: "blur", message: "租户不能为空" },
+          {
+            validator: (rule, value, callback) => {
+              // debugger
+              getTenantIdByName(value).then(res => {
+                const tenantId = res.data;
+                if (tenantId >= 0) {
+                  // 设置租户
+                  Cookies.set("tenantId", tenantId);
+                  callback();
+                } else {
+                  callback('租户不存在');
+                }
+              });
+            },
+            trigger: 'blur'
+          }
+        ],
         username: [
         username: [
           { required: true, trigger: "blur", message: "用户名不能为空" }
           { required: true, trigger: "blur", message: "用户名不能为空" }
         ],
         ],
@@ -103,25 +129,31 @@ export default {
       const username = Cookies.get("username");
       const username = Cookies.get("username");
       const password = Cookies.get("password");
       const password = Cookies.get("password");
       const rememberMe = Cookies.get('rememberMe')
       const rememberMe = Cookies.get('rememberMe')
+      const tenantName = Cookies.get('tenantName');
       this.loginForm = {
       this.loginForm = {
         username: username === undefined ? this.loginForm.username : username,
         username: username === undefined ? this.loginForm.username : username,
         password: password === undefined ? this.loginForm.password : decrypt(password),
         password: password === undefined ? this.loginForm.password : decrypt(password),
-        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
+        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
+        tenantName: tenantName === undefined ? this.loginForm.tenantName : tenantName,
       };
       };
     },
     },
     handleLogin() {
     handleLogin() {
       this.$refs.loginForm.validate(valid => {
       this.$refs.loginForm.validate(valid => {
         if (valid) {
         if (valid) {
           this.loading = true;
           this.loading = true;
+          // 设置 Cookie
           if (this.loginForm.rememberMe) {
           if (this.loginForm.rememberMe) {
             Cookies.set("username", this.loginForm.username, { expires: 30 });
             Cookies.set("username", this.loginForm.username, { expires: 30 });
             Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
             Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
             Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
             Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
+            Cookies.set('tenantName', this.loginForm.tenantName, { expires: 30 });
           } else {
           } else {
             Cookies.remove("username");
             Cookies.remove("username");
             Cookies.remove("password");
             Cookies.remove("password");
             Cookies.remove('rememberMe');
             Cookies.remove('rememberMe');
+            Cookies.remove('tenantName');
           }
           }
+          // 发起登陆
           this.$store.dispatch("Login", this.loginForm).then(() => {
           this.$store.dispatch("Login", this.loginForm).then(() => {
             this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
             this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
           }).catch(() => {
           }).catch(() => {
@@ -167,7 +199,7 @@ export default {
 .login-form {
 .login-form {
   border-radius: 6px;
   border-radius: 6px;
   background: #ffffff;
   background: #ffffff;
-  width: 400px;
+  width: 500px;
   padding: 25px 25px 5px 25px;
   padding: 25px 25px 5px 25px;
   .el-input {
   .el-input {
     height: 38px;
     height: 38px;

+ 259 - 0
yudao-admin-ui/src/views/system/tenant/index.vue

@@ -0,0 +1,259 @@
+<template>
+  <div class="app-container">
+
+    <!-- 搜索工作栏 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="租户名" prop="name">
+        <el-input v-model="queryParams.name" placeholder="请输入租户名" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="联系人" prop="contactName">
+        <el-input v-model="queryParams.contactName" placeholder="请输入联系人" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="联系手机" prop="contactMobile">
+        <el-input v-model="queryParams.contactMobile" placeholder="请输入联系手机" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="租户状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择租户状态" clearable size="small">
+          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
+                       :key="dict.value" :label="dict.label" :value="dict.value"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
+                        type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-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="el-icon-plus" size="mini" @click="handleAdd"
+                   v-hasPermi="['system:tenant:create']">新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
+                   v-hasPermi="['system:tenant:export']">导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <!-- 列表 -->
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="租户编号" align="center" prop="id" />
+      <el-table-column label="租户名" align="center" prop="name" />
+      <el-table-column label="联系人" align="center" prop="contactName" />
+      <el-table-column label="联系手机" align="center" prop="contactMobile" />
+      <el-table-column label="租户状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <span>{{ getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, scope.row.status) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+                     v-hasPermi="['system:tenant:update']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+                     v-hasPermi="['system:tenant:delete']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页组件 -->
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
+
+    <!-- 对话框(添加 / 修改) -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="租户名" prop="name">
+          <el-input v-model="form.name" placeholder="请输入租户名" />
+        </el-form-item>
+        <el-form-item label="联系人" prop="contactName">
+          <el-input v-model="form.contactName" placeholder="请输入联系人" />
+        </el-form-item>
+        <el-form-item label="联系手机" prop="contactMobile">
+          <el-input v-model="form.contactMobile" placeholder="请输入联系手机" />
+        </el-form-item>
+        <el-form-item label="租户状态" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
+                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { createTenant, updateTenant, deleteTenant, getTenant, getTenantPage, exportTenantExcel } from "@/api/system/tenant";
+import { SysCommonStatusEnum } from '@/utils/constants'
+
+export default {
+  name: "Tenant",
+  components: {
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 租户列表
+      list: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      dateRangeCreateTime: [],
+      // 查询参数
+      queryParams: {
+        pageNo: 1,
+        pageSize: 10,
+        name: null,
+        contactName: null,
+        contactMobile: null,
+        status: undefined,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        name: [{ required: true, message: "租户名不能为空", trigger: "blur" }],
+        contactName: [{ required: true, message: "联系人不能为空", trigger: "blur" }],
+        status: [{ required: true, message: "租户状态(0正常 1停用)不能为空", trigger: "blur" }],
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询列表 */
+    getList() {
+      this.loading = true;
+      // 处理查询参数
+      let params = {...this.queryParams};
+      this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
+      // 执行查询
+      getTenantPage(params).then(response => {
+        this.list = response.data.list;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    /** 取消按钮 */
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    /** 表单重置 */
+    reset() {
+      this.form = {
+        id: undefined,
+        name: undefined,
+        contactName: undefined,
+        contactMobile: undefined,
+        status: SysCommonStatusEnum.ENABLE,
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNo = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRangeCreateTime = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加租户";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id;
+      getTenant(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改租户";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (!valid) {
+          return;
+        }
+        // 修改的提交
+        if (this.form.id != null) {
+          updateTenant(this.form).then(response => {
+            this.msgSuccess("修改成功");
+            this.open = false;
+            this.getList();
+          });
+          return;
+        }
+        // 添加的提交
+        createTenant(this.form).then(response => {
+          this.msgSuccess("新增成功");
+          this.open = false;
+          this.getList();
+        });
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const id = row.id;
+      this.$confirm('是否确认删除租户编号为"' + id + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return deleteTenant(id);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      // 处理查询参数
+      let params = {...this.queryParams};
+      params.pageNo = undefined;
+      params.pageSize = undefined;
+      this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
+      // 执行导出
+      this.$confirm('是否确认导出所有租户数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportTenantExcel(params);
+        }).then(response => {
+          this.downloadExcel(response, '租户.xls');
+        })
+    }
+  }
+};
+</script>

+ 9 - 6
yudao-core-service/pom.xml

@@ -36,6 +36,14 @@
             <groupId>cn.iocoder.boot</groupId>
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-biz-pay</artifactId>
             <artifactId>yudao-spring-boot-starter-biz-pay</artifactId>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-social</artifactId>
+        </dependency>
 
 
         <!-- Web 相关 -->
         <!-- Web 相关 -->
         <dependency>
         <dependency>
@@ -91,17 +99,12 @@
         </dependency>
         </dependency>
 
 
         <!-- 工具类相关 -->
         <!-- 工具类相关 -->
+
         <dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <artifactId>guava</artifactId>
         </dependency>
         </dependency>
 
 
-        <!-- 三方云服务相关 -->
-        <dependency>
-            <groupId>com.xkcoding.justauth</groupId>
-            <artifactId>justauth-spring-boot-starter</artifactId>
-        </dependency>
-
     </dependencies>
     </dependencies>
 
 
 </project>
 </project>

+ 2 - 1
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file;
 package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file;
 
 
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -21,7 +22,7 @@ import java.io.InputStream;
 @Builder
 @Builder
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
-public class InfFileDO extends BaseDO {
+public class InfFileDO extends TenantBaseDO {
 
 
     /**
     /**
      * 文件路径
      * 文件路径

+ 2 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java

@@ -2,7 +2,7 @@ package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger;
 
 
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 import lombok.*;
@@ -21,7 +21,7 @@ import java.util.Date;
 @Builder
 @Builder
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
-public class InfApiAccessLogDO extends BaseDO {
+public class InfApiAccessLogDO extends TenantBaseDO {
 
 
     /**
     /**
      * 编号
      * 编号

+ 3 - 3
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger;
 package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger;
 
 
-import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.coreservice.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
 import cn.iocoder.yudao.coreservice.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 import lombok.*;
@@ -21,7 +21,7 @@ import java.util.Date;
 @Builder
 @Builder
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
-public class InfApiErrorLogDO extends BaseDO {
+public class InfApiErrorLogDO extends TenantBaseDO {
 
 
     /**
     /**
      * 编号
      * 编号

+ 16 - 0
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/file/InfFileCoreMapper.java

@@ -2,11 +2,27 @@ package cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file;
 
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
 
 
 @Mapper
 @Mapper
 public interface InfFileCoreMapper extends BaseMapperX<InfFileDO> {
 public interface InfFileCoreMapper extends BaseMapperX<InfFileDO> {
+
     default Integer selectCountById(String id) {
     default Integer selectCountById(String id) {
         return selectCount("id", id);
         return selectCount("id", id);
     }
     }
+
+    /**
+     * 基于 Path 获取文件
+     * 实际上,是基于 ID 查询
+     * 由于前端使用 <img /> 的方式获取图片,所以需要忽略租户的查询
+     *
+     * @param path 路径
+     * @return 文件
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    default InfFileDO selectByPath(String path) {
+        return selectById(path);
+    }
+
 }
 }

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels