Procházet zdrojové kódy

!58 新增多租户、数据权限
Merge pull request !58 from 芋道源码/feature/user-register

芋道源码 před 3 roky
rodič
revize
ac1ced7459
100 změnil soubory, kde provedl 1746 přidání a 289 odebrání
  1. 1 0
      README.md
  2. binární
      img.png
  3. 8 0
      yudao-admin-server/pom.xml
  4. 0 9
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/config/AsyncConfiguration.java
  5. 0 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/package-info.java
  6. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java
  7. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java
  8. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java
  9. 5 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http
  10. 106 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java
  11. 30 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java
  12. 14 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java
  13. 39 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java
  14. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java
  15. 41 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java
  16. 19 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java
  17. 18 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java
  18. 2 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http
  19. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java
  20. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java
  21. 2 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java
  22. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/logger/SysOperateLogDO.java
  23. 3 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java
  24. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java
  25. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/permission/SysMenuMapper.java
  26. 44 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java
  27. 3 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
  28. 7 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/captcha/config/CaptchaProperties.java
  29. 25 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java
  30. 4 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java
  31. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/job/auth/SysUserSessionTimeoutJob.java
  32. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java
  33. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java
  34. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java
  35. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java
  36. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java
  37. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java
  38. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java
  39. 6 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java
  40. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java
  41. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java
  42. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java
  43. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java
  44. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java
  45. 4 7
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java
  46. 23 18
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
  47. 7 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java
  48. 5 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java
  49. 8 5
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/impl/SysDeptServiceImpl.java
  50. 2 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java
  51. 70 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysPermissionServiceImpl.java
  52. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/impl/SysRoleServiceImpl.java
  53. 83 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java
  54. 91 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java
  55. 4 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenEngine.java
  56. 1 0
      yudao-admin-server/src/main/resources/application-dev.yaml
  57. 3 0
      yudao-admin-server/src/main/resources/application-local.yaml
  58. 3 1
      yudao-admin-server/src/main/resources/application.yaml
  59. 5 5
      yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm
  60. 1 0
      yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml
  61. 8 8
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/config/InfConfigServiceTest.java
  62. 3 3
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java
  63. 11 11
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobLogServiceTest.java
  64. 7 7
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/job/InfJobServiceTest.java
  65. 14 14
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java
  66. 17 18
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java
  67. 6 1
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java
  68. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionServiceImplTest.java
  69. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java
  70. 4 4
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java
  71. 6 9
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictDataServiceTest.java
  72. 8 8
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dict/SysDictTypeServiceTest.java
  73. 5 5
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/errorcode/SysErrorCodeServiceTest.java
  74. 8 8
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysLoginLogServiceImplTest.java
  75. 10 10
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/logger/SysOperateLogServiceImplTest.java
  76. 2 2
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java
  77. 121 1
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java
  78. 4 4
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysRoleServiceTest.java
  79. 3 3
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsChannelServiceTest.java
  80. 14 14
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsLogServiceTest.java
  81. 14 14
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/sms/SysSmsTemplateServiceTest.java
  82. 181 0
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java
  83. 5 5
      yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java
  84. 1 0
      yudao-admin-server/src/test/resources/sql/clean.sql
  85. 26 3
      yudao-admin-server/src/test/resources/sql/create_tables.sql
  86. 54 0
      yudao-admin-ui/src/api/system/tenant.js
  87. 6 0
      yudao-admin-ui/src/utils/request.js
  88. 35 3
      yudao-admin-ui/src/views/login.vue
  89. 259 0
      yudao-admin-ui/src/views/system/tenant/index.vue
  90. 5 0
      yudao-core-service/pom.xml
  91. 2 1
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java
  92. 2 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java
  93. 3 3
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java
  94. 2 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java
  95. 2 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java
  96. 45 0
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/tenant/SysTenantDO.java
  97. 2 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/user/SysUserDO.java
  98. 9 0
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/tenant/SysTenantCoreMapper.java
  99. 4 2
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/sms/SysSmsSendMessage.java
  100. 3 4
      yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/sms/SysSmsCoreProducer.java

+ 1 - 0
README.md

@@ -33,6 +33,7 @@
 |  | 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等 |
 |  | 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等 |
 |  | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
 |  | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
 |  | 岗位管理 | 配置系统用户所属担任职务 |
 |  | 岗位管理 | 配置系统用户所属担任职务 |
+|  | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
 |  | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
 |  | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
 | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 |
 | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 |
 | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
 | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |

binární
img.png


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

@@ -117,7 +117,15 @@
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
         </dependency>
         </dependency>
 
 
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-tenant</artifactId>
+        </dependency>
 
 
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-data-permission</artifactId>
+        </dependency>
 
 
         <dependency>
         <dependency>
             <groupId>org.apache.velocity</groupId>
             <groupId>org.apache.velocity</groupId>

+ 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 - 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

+ 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

+ 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);
     }
     }
 
 
 }
 }

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

@@ -92,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
@@ -107,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
@@ -117,10 +113,9 @@ 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);
     }
     }
@@ -133,9 +128,13 @@ public class SysAuthServiceImpl implements SysAuthService {
     }
     }
 
 
     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);
@@ -230,8 +229,7 @@ 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, userTypeEnum);
@@ -248,7 +246,6 @@ 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, userTypeEnum);
@@ -301,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 信息
@@ -319,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 - 5
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));
     }
     }
 
 

+ 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);
+    }
+
+}

+ 4 - 0
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());

+ 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 # 打印日志
@@ -73,5 +73,7 @@ yudao:
     constants-class-list:
     constants-class-list:
       - 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
+  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 - 0
yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml

@@ -6,6 +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="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("艿");

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

@@ -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();

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

@@ -17,6 +17,7 @@ import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreServi
 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;
@@ -71,6 +72,11 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
     @MockBean
     @MockBean
     private SysPostService postService;
     private SysPostService postService;
 
 
+    @BeforeEach
+    public void setUp() {
+        when(captchaService.isCaptchaEnable()).thenReturn(true);
+    }
+
     @Test
     @Test
     public void testLoadUserByUsername_success() {
     public void testLoadUserByUsername_success() {
         // 准备参数
         // 准备参数
@@ -83,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 '租户';

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

@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 创建租户
+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>

+ 5 - 0
yudao-core-service/pom.xml

@@ -91,6 +91,11 @@
         </dependency>
         </dependency>
 
 
         <!-- 工具类相关 -->
         <!-- 工具类相关 -->
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-tenant</artifactId>
+        </dependency>
+
         <dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <artifactId>guava</artifactId>

+ 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 {
 
 
     /**
     /**
      * 编号
      * 编号

+ 2 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user;
 package cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user;
 
 
 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.*;
 import lombok.*;
@@ -22,7 +22,7 @@ import java.util.Date;
 @Builder
 @Builder
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
-public class MbrUserDO extends BaseDO {
+public class MbrUserDO extends TenantBaseDO {
 
 
     /**
     /**
      * 用户ID
      * 用户ID

+ 2 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth;
 package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth;
 
 
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
 import cn.iocoder.yudao.framework.security.core.LoginUser;
+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.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -25,7 +25,7 @@ import java.util.Date;
 @Data
 @Data
 @Builder
 @Builder
 @EqualsAndHashCode(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
-public class SysUserSessionDO extends BaseDO {
+public class SysUserSessionDO extends TenantBaseDO {
 
 
     /**
     /**
      * 会话编号, 即 sessionId
      * 会话编号, 即 sessionId

+ 45 - 0
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/tenant/SysTenantDO.java

@@ -0,0 +1,45 @@
+package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * 租户 DO
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "sys_tenant", autoResultMap = true)
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class SysTenantDO extends BaseDO {
+
+    /**
+     * 租户编号,自增
+     */
+    private Long id;
+    /**
+     * 租户名,唯一
+     */
+    private String name;
+    /**
+     * 联系人
+     */
+    private String contactName;
+    /**
+     * 联系手机
+     */
+    private String contactMobile;
+    /**
+     * 帐号状态
+     *
+     * 枚举 {@link CommonStatusEnum}
+     */
+    private Integer status;
+
+}

+ 2 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/user/SysUserDO.java

@@ -2,8 +2,8 @@ package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user;
 
 
 import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum;
 import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum;
 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.mybatis.core.type.JsonLongSetTypeHandler;
 import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
+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;
@@ -24,7 +24,7 @@ import java.util.Set;
 @Builder
 @Builder
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
-public class SysUserDO extends BaseDO {
+public class SysUserDO extends TenantBaseDO {
 
 
     /**
     /**
      * 用户ID
      * 用户ID

+ 9 - 0
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/tenant/SysTenantCoreMapper.java

@@ -0,0 +1,9 @@
+package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.tenant;
+
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SysTenantCoreMapper extends BaseMapperX<SysTenantDO> {
+}

+ 4 - 2
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/sms/SysSmsSendMessage.java

@@ -1,8 +1,9 @@
 package cn.iocoder.yudao.coreservice.modules.system.mq.message.sms;
 package cn.iocoder.yudao.coreservice.modules.system.mq.message.sms;
 
 
 import cn.iocoder.yudao.framework.common.core.KeyValue;
 import cn.iocoder.yudao.framework.common.core.KeyValue;
-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.List;
 import java.util.List;
@@ -13,7 +14,8 @@ import java.util.List;
  * @author 芋道源码
  * @author 芋道源码
  */
  */
 @Data
 @Data
-public class SysSmsSendMessage implements StreamMessage {
+@EqualsAndHashCode(callSuper = true)
+public class SysSmsSendMessage extends AbstractStreamMessage {
 
 
     /**
     /**
      * 短信日志编号
      * 短信日志编号

+ 3 - 4
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/producer/sms/SysSmsCoreProducer.java

@@ -2,9 +2,8 @@ package cn.iocoder.yudao.coreservice.modules.system.mq.producer.sms;
 
 
 import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage;
 import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage;
 import cn.iocoder.yudao.framework.common.core.KeyValue;
 import cn.iocoder.yudao.framework.common.core.KeyValue;
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
+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;
@@ -21,7 +20,7 @@ import java.util.List;
 public class SysSmsCoreProducer {
 public class SysSmsCoreProducer {
 
 
     @Resource
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
 
     /**
     /**
      * 发送 {@link SysSmsSendMessage} 消息
      * 发送 {@link SysSmsSendMessage} 消息
@@ -36,7 +35,7 @@ public class SysSmsCoreProducer {
                                    Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
                                    Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
         SysSmsSendMessage message = new SysSmsSendMessage().setLogId(logId).setMobile(mobile);
         SysSmsSendMessage message = new SysSmsSendMessage().setLogId(logId).setMobile(mobile);
         message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
         message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
-        RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
     }
 
 
 }
 }

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů